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

Last change on this file since 59339 was 59339, checked in by [email protected], 15 years ago

https://bugs.webkit.org/show_bug.cgi?id=39039
Provide support for separate bytecode/JIT code translations for call/construct usage
This will allow us to produce code generated specifically for use as a constructor, not for general function use.

Reviewed by Oliver Hunt.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::unlinkCallers):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::getBytecodeIndex):
(JSC::CodeBlock::getJITCode):
(JSC::CodeBlock::executablePool):
(JSC::GlobalCodeBlock::GlobalCodeBlock):
(JSC::FunctionCodeBlock::FunctionCodeBlock):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
(JSC::Interpreter::execute):
(JSC::Interpreter::privateExecute):

  • interpreter/Interpreter.h:
  • jit/JIT.cpp:

(JSC::JIT::unlinkCallOrConstruct):
(JSC::JIT::linkConstruct):

  • jit/JIT.h:
  • jit/JITCall.cpp:

(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):

  • jit/JITOpcodes.cpp:

(JSC::JIT::privateCompileCTIMachineTrampolines):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::privateCompileCTIMachineTrampolines):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emitSlow_op_get_by_val):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emitSlow_op_get_by_val):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • jit/JITStubs.h:

(JSC::JITThunks::ctiVirtualConstructLink):
(JSC::JITThunks::ctiVirtualConstruct):
(JSC::):

  • jit/SpecializedThunkJIT.h:

(JSC::SpecializedThunkJIT::finalize):

  • runtime/Arguments.h:

(JSC::JSActivation::copyRegisters):

  • runtime/ArrayPrototype.cpp:

(JSC::isNumericCompareFunction):

  • runtime/Executable.cpp:

(JSC::FunctionExecutable::~FunctionExecutable):
(JSC::FunctionExecutable::compileForCall):
(JSC::FunctionExecutable::compileForConstruct):
(JSC::EvalExecutable::generateJITCode):
(JSC::ProgramExecutable::generateJITCode):
(JSC::FunctionExecutable::generateJITCodeForCall):
(JSC::FunctionExecutable::generateJITCodeForConstruct):
(JSC::FunctionExecutable::markAggregate):
(JSC::FunctionExecutable::reparseExceptionInfo):
(JSC::EvalExecutable::reparseExceptionInfo):
(JSC::FunctionExecutable::recompile):

  • runtime/Executable.h:

(JSC::ExecutableBase::ExecutableBase):
(JSC::ExecutableBase::isHostFunction):
(JSC::ExecutableBase::generatedJITCodeForCall):
(JSC::ExecutableBase::generatedJITCodeForConstruct):
(JSC::NativeExecutable::NativeExecutable):
(JSC::EvalExecutable::jitCode):
(JSC::ProgramExecutable::jitCode):
(JSC::FunctionExecutable::bytecodeForCall):
(JSC::FunctionExecutable::isGeneratedForCall):
(JSC::FunctionExecutable::generatedBytecodeForCall):
(JSC::FunctionExecutable::bytecodeForConstruct):
(JSC::FunctionExecutable::isGeneratedForConstruct):
(JSC::FunctionExecutable::generatedBytecodeForConstruct):
(JSC::FunctionExecutable::symbolTable):
(JSC::FunctionExecutable::FunctionExecutable):
(JSC::FunctionExecutable::jitCodeForCall):
(JSC::FunctionExecutable::jitCodeForConstruct):

  • runtime/JSActivation.h:

(JSC::JSActivation::JSActivationData::JSActivationData):

  • runtime/JSFunction.cpp:

(JSC::JSFunction::~JSFunction):
(JSC::JSFunction::call):
(JSC::JSFunction::construct):

  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::numericCompareFunction):

  • Property svn:eol-style set to native
File size: 10.1 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
48bool JSFunction::isHostFunctionNonInline() const
49{
50 return isHostFunction();
51}
52
53JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure)
54 : Base(structure)
55 , m_executable(adoptRef(new VPtrHackExecutable()))
56{
57}
58
59JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeExecutable* thunk, NativeFunction func)
60 : Base(&exec->globalData(), structure, name)
61#if ENABLE(JIT)
62 , m_executable(thunk)
63#endif
64{
65#if ENABLE(JIT)
66 setNativeFunction(func);
67 putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
68#else
69 UNUSED_PARAM(thunk);
70 UNUSED_PARAM(length);
71 UNUSED_PARAM(func);
72 ASSERT_NOT_REACHED();
73#endif
74}
75
76JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
77 : Base(&exec->globalData(), structure, name)
78#if ENABLE(JIT)
79 , m_executable(exec->globalData().jitStubs.ctiNativeCallThunk())
80#endif
81{
82#if ENABLE(JIT)
83 setNativeFunction(func);
84 putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
85#else
86 UNUSED_PARAM(length);
87 UNUSED_PARAM(func);
88 ASSERT_NOT_REACHED();
89#endif
90}
91
92JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode)
93 : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), executable->name())
94 , m_executable(executable)
95{
96 setScopeChain(scopeChainNode);
97}
98
99JSFunction::~JSFunction()
100{
101 ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
102
103 // JIT code for other functions may have had calls linked directly to the code for this function; these links
104 // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
105 // this memory is freed and may be reused (potentially for another, different JSFunction).
106 if (!isHostFunction()) {
107#if ENABLE(JIT_OPTIMIZE_CALL)
108 ASSERT(m_executable);
109 if (jsExecutable()->isGeneratedForCall())
110 jsExecutable()->generatedBytecodeForCall().unlinkCallers();
111 if (jsExecutable()->isGeneratedForConstruct())
112 jsExecutable()->generatedBytecodeForConstruct().unlinkCallers();
113#endif
114 scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
115 }
116}
117
118void JSFunction::markChildren(MarkStack& markStack)
119{
120 Base::markChildren(markStack);
121 if (!isHostFunction()) {
122 jsExecutable()->markAggregate(markStack);
123 scopeChain().markAggregate(markStack);
124 }
125}
126
127CallType JSFunction::getCallData(CallData& callData)
128{
129 if (isHostFunction()) {
130 callData.native.function = nativeFunction();
131 return CallTypeHost;
132 }
133 callData.js.functionExecutable = jsExecutable();
134 callData.js.scopeChain = scopeChain().node();
135 return CallTypeJS;
136}
137
138JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args)
139{
140 ASSERT(!isHostFunction());
141 return exec->interpreter()->executeCall(jsExecutable(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot());
142}
143
144JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&)
145{
146 JSFunction* thisObj = asFunction(slotBase);
147 ASSERT(!thisObj->isHostFunction());
148 return exec->interpreter()->retrieveArguments(exec, thisObj);
149}
150
151JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identifier&)
152{
153 JSFunction* thisObj = asFunction(slotBase);
154 ASSERT(!thisObj->isHostFunction());
155 return exec->interpreter()->retrieveCaller(exec, thisObj);
156}
157
158JSValue JSFunction::lengthGetter(ExecState* exec, JSValue slotBase, const Identifier&)
159{
160 JSFunction* thisObj = asFunction(slotBase);
161 ASSERT(!thisObj->isHostFunction());
162 return jsNumber(exec, thisObj->jsExecutable()->parameterCount());
163}
164
165bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
166{
167 if (isHostFunction())
168 return Base::getOwnPropertySlot(exec, propertyName, slot);
169
170 if (propertyName == exec->propertyNames().prototype) {
171 JSValue* location = getDirectLocation(propertyName);
172
173 if (!location) {
174 JSObject* prototype = new (exec) JSObject(scopeChain().globalObject()->emptyObjectStructure());
175 prototype->putDirect(exec->propertyNames().constructor, this, DontEnum);
176 putDirect(exec->propertyNames().prototype, prototype, DontDelete);
177 location = getDirectLocation(propertyName);
178 }
179
180 slot.setValueSlot(this, location, offsetForLocation(location));
181 }
182
183 if (propertyName == exec->propertyNames().arguments) {
184 slot.setCacheableCustom(this, argumentsGetter);
185 return true;
186 }
187
188 if (propertyName == exec->propertyNames().length) {
189 slot.setCacheableCustom(this, lengthGetter);
190 return true;
191 }
192
193 if (propertyName == exec->propertyNames().caller) {
194 slot.setCacheableCustom(this, callerGetter);
195 return true;
196 }
197
198 return Base::getOwnPropertySlot(exec, propertyName, slot);
199}
200
201 bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
202 {
203 if (isHostFunction())
204 return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
205
206 if (propertyName == exec->propertyNames().prototype) {
207 PropertySlot slot;
208 getOwnPropertySlot(exec, propertyName, slot);
209 return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
210 }
211
212 if (propertyName == exec->propertyNames().arguments) {
213 descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
214 return true;
215 }
216
217 if (propertyName == exec->propertyNames().length) {
218 descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
219 return true;
220 }
221
222 if (propertyName == exec->propertyNames().caller) {
223 descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete);
224 return true;
225 }
226
227 return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
228 }
229
230void JSFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
231{
232 if (!isHostFunction() && (mode == IncludeDontEnumProperties)) {
233 propertyNames.add(exec->propertyNames().arguments);
234 propertyNames.add(exec->propertyNames().callee);
235 propertyNames.add(exec->propertyNames().caller);
236 propertyNames.add(exec->propertyNames().length);
237 }
238 Base::getOwnPropertyNames(exec, propertyNames, mode);
239}
240
241void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
242{
243 if (isHostFunction()) {
244 Base::put(exec, propertyName, value, slot);
245 return;
246 }
247 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
248 return;
249 Base::put(exec, propertyName, value, slot);
250}
251
252bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)
253{
254 if (isHostFunction())
255 return Base::deleteProperty(exec, propertyName);
256 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
257 return false;
258 return Base::deleteProperty(exec, propertyName);
259}
260
261// ECMA 13.2.2 [[Construct]]
262ConstructType JSFunction::getConstructData(ConstructData& constructData)
263{
264 if (isHostFunction())
265 return ConstructTypeNone;
266 constructData.js.functionExecutable = jsExecutable();
267 constructData.js.scopeChain = scopeChain().node();
268 return ConstructTypeJS;
269}
270
271JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
272{
273 ASSERT(!isHostFunction());
274 Structure* structure;
275 JSValue prototype = get(exec, exec->propertyNames().prototype);
276 if (prototype.isObject())
277 structure = asObject(prototype)->inheritorID();
278 else
279 structure = exec->lexicalGlobalObject()->emptyObjectStructure();
280 JSObject* thisObj = new (exec) JSObject(structure);
281
282 JSValue result = exec->interpreter()->executeConstruct(jsExecutable(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
283 if (exec->hadException() || !result.isObject())
284 return thisObj;
285 return asObject(result);
286}
287
288} // namespace JSC
Note: See TracBrowser for help on using the repository browser.