source: webkit/trunk/JavaScriptCore/runtime/JSFunction.cpp@ 47620

Last change on this file since 47620 was 47597, checked in by [email protected], 16 years ago

Remove FunctionCodeBlock.
https://bugs.webkit.org/show_bug.cgi?id=28502

Reviewed by Oliver Hunt.

These only exist to allow JIT code to dereference properties off the
CodeBlock for any callee, regardless of whether it is a host function.

Instead just use the FunctionExecutable. Copy the m_parameters field
from the CodeBlock into the Executable, and use this to distinguish
between host functions, functions that have been bytecompiled, and
functions that have not.

m_parameters is moved to ExecutableBase rather than FunctionExecutable
so that (as a separate change) we can move make a separate class of
executable for host code, which is not devived from FunctionExecutable
(host code does not feature any of the properties that normal executable
do and will provide, such as source, attributes, and a parsed name).

1% win on v8 tests, 0.5% on sunspider.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::derefStructures):
(JSC::CodeBlock::refStructures):
(JSC::CodeBlock::reparseForExceptionInfoIfNecessary):
(JSC::CodeBlock::handlerForBytecodeOffset):
(JSC::CodeBlock::lineNumberForBytecodeOffset):
(JSC::CodeBlock::expressionRangeForBytecodeOffset):
(JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset):
(JSC::CodeBlock::functionRegisterForBytecodeOffset):
(JSC::CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset):
(JSC::CodeBlock::hasGlobalResolveInfoAtBytecodeOffset):

  • bytecode/CodeBlock.h:

(JSC::):
(JSC::CodeBlock::source):
(JSC::CodeBlock::sourceOffset):
(JSC::CodeBlock::evalCodeCache):
(JSC::CodeBlock::createRareDataIfNecessary):

remove NativeCodeBlocks and the NativeCode code type.


  • jit/JIT.cpp:

(JSC::JIT::linkCall):

Revert to previous behaviour (as currently still commented!) that Hhost functions have a null codeblock.

  • jit/JITCall.cpp:

(JSC::JIT::compileOpCallInitializeCallFrame):
(JSC::JIT::compileOpCallSetupArgs):
(JSC::JIT::compileOpCallVarargsSetupArgs):
(JSC::JIT::compileOpConstructSetupArgs):
(JSC::JIT::compileOpCallVarargs):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):

Bring the 32_64 & non-32_64 JITs into line with each other, callee in regT0.

  • jit/JITOpcodes.cpp:

(JSC::JIT::privateCompileCTIMachineTrampolines):

Rewrite call trampolines to not use the CodeBlock.

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

Make call_JSFunction & call_arityCheck return the callee, don't expect to be passed the CodeBlock.

  • runtime/Executable.cpp:

(JSC::FunctionExecutable::generateBytecode):
(JSC::FunctionExecutable::recompile):
(JSC::FunctionExecutable::FunctionExecutable):

  • runtime/Executable.h:

(JSC::ExecutableBase::):
(JSC::ExecutableBase::ExecutableBase):
(JSC::FunctionExecutable::isHostFunction):

Add m_numParameters.

  • runtime/JSFunction.cpp:

(JSC::JSFunction::~JSFunction):

Only call generatedBytecode() on JSFunctions non-host FunctionExecutables.

  • Property svn:eol-style set to native
File size: 7.7 KB
Line 
1/*
2 * Copyright (C) 1999-2002 Harri Porten ([email protected])
3 * Copyright (C) 2001 Peter Kelly ([email protected])
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Cameron Zwarich ([email protected])
6 * Copyright (C) 2007 Maks Orlovich
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#include "config.h"
26#include "JSFunction.h"
27
28#include "CodeBlock.h"
29#include "CommonIdentifiers.h"
30#include "CallFrame.h"
31#include "FunctionPrototype.h"
32#include "JSGlobalObject.h"
33#include "Interpreter.h"
34#include "ObjectPrototype.h"
35#include "Parser.h"
36#include "PropertyNameArray.h"
37#include "ScopeChainMark.h"
38
39using namespace WTF;
40using namespace Unicode;
41
42namespace JSC {
43
44ASSERT_CLASS_FITS_IN_CELL(JSFunction);
45
46const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };
47
48inline bool JSFunction::isHostFunction() const
49{
50 return m_executable && m_executable->isHostFunction();
51}
52
53bool JSFunction::isHostFunctionNonInline() const
54{
55 return isHostFunction();
56}
57
58JSFunction::JSFunction(PassRefPtr<Structure> structure)
59 : Base(structure)
60{
61 clearScopeChain();
62}
63
64JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
65 : Base(&exec->globalData(), structure, name)
66#if ENABLE(JIT)
67 , m_executable(FunctionExecutable::createNativeThunk(exec))
68#endif
69{
70#if ENABLE(JIT)
71 setNativeFunction(func);
72 putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
73#else
74 UNUSED_PARAM(length);
75 UNUSED_PARAM(func);
76 ASSERT_NOT_REACHED();
77#endif
78}
79
80JSFunction::JSFunction(ExecState* exec, PassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode)
81 : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), executable->name())
82 , m_executable(executable)
83{
84 setScopeChain(scopeChainNode);
85}
86
87JSFunction::~JSFunction()
88{
89 // JIT code for other functions may have had calls linked directly to the code for this function; these links
90 // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
91 // this memory is freed and may be reused (potentially for another, different JSFunction).
92 if (!isHostFunction()) {
93#if ENABLE(JIT_OPTIMIZE_CALL)
94 if (m_executable && m_executable->isGenerated())
95 m_executable->generatedBytecode().unlinkCallers();
96#endif
97 scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
98 }
99}
100
101void JSFunction::markChildren(MarkStack& markStack)
102{
103 Base::markChildren(markStack);
104 m_executable->markAggregate(markStack);
105 if (!isHostFunction())
106 scopeChain().markAggregate(markStack);
107}
108
109CallType JSFunction::getCallData(CallData& callData)
110{
111 if (isHostFunction()) {
112 callData.native.function = nativeFunction();
113 return CallTypeHost;
114 }
115 callData.js.functionExecutable = m_executable.get();
116 callData.js.scopeChain = scopeChain().node();
117 return CallTypeJS;
118}
119
120JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args)
121{
122 ASSERT(!isHostFunction());
123 return exec->interpreter()->execute(m_executable.get(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot());
124}
125
126JSValue JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
127{
128 JSFunction* thisObj = asFunction(slot.slotBase());
129 ASSERT(!thisObj->isHostFunction());
130 return exec->interpreter()->retrieveArguments(exec, thisObj);
131}
132
133JSValue JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
134{
135 JSFunction* thisObj = asFunction(slot.slotBase());
136 ASSERT(!thisObj->isHostFunction());
137 return exec->interpreter()->retrieveCaller(exec, thisObj);
138}
139
140JSValue JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
141{
142 JSFunction* thisObj = asFunction(slot.slotBase());
143 ASSERT(!thisObj->isHostFunction());
144 return jsNumber(exec, thisObj->m_executable->parameterCount());
145}
146
147bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
148{
149 if (isHostFunction())
150 return Base::getOwnPropertySlot(exec, propertyName, slot);
151
152 if (propertyName == exec->propertyNames().prototype) {
153 JSValue* location = getDirectLocation(propertyName);
154
155 if (!location) {
156 JSObject* prototype = new (exec) JSObject(scopeChain().globalObject()->emptyObjectStructure());
157 prototype->putDirect(exec->propertyNames().constructor, this, DontEnum);
158 putDirect(exec->propertyNames().prototype, prototype, DontDelete);
159 location = getDirectLocation(propertyName);
160 }
161
162 slot.setValueSlot(this, location, offsetForLocation(location));
163 }
164
165 if (propertyName == exec->propertyNames().arguments) {
166 slot.setCustom(this, argumentsGetter);
167 return true;
168 }
169
170 if (propertyName == exec->propertyNames().length) {
171 slot.setCustom(this, lengthGetter);
172 return true;
173 }
174
175 if (propertyName == exec->propertyNames().caller) {
176 slot.setCustom(this, callerGetter);
177 return true;
178 }
179
180 return Base::getOwnPropertySlot(exec, propertyName, slot);
181}
182
183void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
184{
185 if (isHostFunction()) {
186 Base::put(exec, propertyName, value, slot);
187 return;
188 }
189 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
190 return;
191 Base::put(exec, propertyName, value, slot);
192}
193
194bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)
195{
196 if (isHostFunction())
197 return Base::deleteProperty(exec, propertyName);
198 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
199 return false;
200 return Base::deleteProperty(exec, propertyName);
201}
202
203// ECMA 13.2.2 [[Construct]]
204ConstructType JSFunction::getConstructData(ConstructData& constructData)
205{
206 if (isHostFunction())
207 return ConstructTypeNone;
208 constructData.js.functionExecutable = m_executable.get();
209 constructData.js.scopeChain = scopeChain().node();
210 return ConstructTypeJS;
211}
212
213JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
214{
215 ASSERT(!isHostFunction());
216 Structure* structure;
217 JSValue prototype = get(exec, exec->propertyNames().prototype);
218 if (prototype.isObject())
219 structure = asObject(prototype)->inheritorID();
220 else
221 structure = exec->lexicalGlobalObject()->emptyObjectStructure();
222 JSObject* thisObj = new (exec) JSObject(structure);
223
224 JSValue result = exec->interpreter()->execute(m_executable.get(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
225 if (exec->hadException() || !result.isObject())
226 return thisObj;
227 return asObject(result);
228}
229
230} // namespace JSC
Note: See TracBrowser for help on using the repository browser.