source: webkit/trunk/JavaScriptCore/runtime/JSActivation.cpp@ 45891

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

JavaScriptCore:

2009-07-07 Gavin Barraclough <[email protected]>

Reviewed by Sam Weinig.

Stop loading constants into the register file.

Instead, use high register values (highest bit bar the sign bit set) to indicate
constants in the instruction stream, and when we encounter such a value load it
directly from the CodeBlock.

Since constants are no longer copied into the register file, this patch renders
the 'unexpected constant' mechanism redundant, and removes it.

2% improvement, thanks to Sam Weinig.

  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump): (JSC::CodeBlock::CodeBlock): (JSC::CodeBlock::mark): (JSC::CodeBlock::shrinkToFit):
  • bytecode/CodeBlock.h: (JSC::CodeBlock::isTemporaryRegisterIndex): (JSC::CodeBlock::constantRegister): (JSC::CodeBlock::isConstantRegisterIndex): (JSC::CodeBlock::getConstant): (JSC::ExecState::r):
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::preserveLastVar): (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::addConstantValue): (JSC::BytecodeGenerator::emitEqualityOp): (JSC::BytecodeGenerator::emitLoad): (JSC::BytecodeGenerator::emitResolveBase): (JSC::BytecodeGenerator::emitResolveWithBase): (JSC::BytecodeGenerator::emitNewError):
  • bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::emitNode):
  • interpreter/CallFrame.h: (JSC::ExecState::noCaller): (JSC::ExecState::hasHostCallFrameFlag): (JSC::ExecState::addHostCallFrameFlag): (JSC::ExecState::removeHostCallFrameFlag):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::resolve): (JSC::Interpreter::resolveSkip): (JSC::Interpreter::resolveGlobal): (JSC::Interpreter::resolveBase): (JSC::Interpreter::resolveBaseAndProperty): (JSC::Interpreter::resolveBaseAndFunc): (JSC::Interpreter::dumpRegisters): (JSC::Interpreter::throwException): (JSC::Interpreter::createExceptionScope): (JSC::Interpreter::privateExecute): (JSC::Interpreter::retrieveArguments):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass):
  • jit/JITInlineMethods.h: (JSC::JIT::emitLoadDouble): (JSC::JIT::emitLoadInt32ToDouble):
  • jit/JITOpcodes.cpp: (JSC::JIT::emit_op_new_error): (JSC::JIT::emit_op_enter): (JSC::JIT::emit_op_enter_with_activation):
  • parser/Nodes.cpp: (JSC::DeleteResolveNode::emitBytecode): (JSC::DeleteValueNode::emitBytecode): (JSC::PrefixResolveNode::emitBytecode):
  • runtime/JSActivation.cpp: (JSC::JSActivation::JSActivation):
  • wtf/Platform.h:

LayoutTests:

2009-07-07 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

fast/js/global-recursion-on-full-stack.html is a little finicky.

The test recurses down the JS stack to find the bottom (catching this with an exception),
then tries to call a host function (document.write), switch writes new '<script>' code,
and expects this code to be run, then expects this code to try to call 'f();' again,
which it expects to fail, and it expects to catch that exception. However it is possible
that one of the earlier stages (the call to document.write, entering the interpreter to
run the new global code) will fail, depending on exactly how much stack space was free at
the point the last call to f() failed.

Tweak the test to make it work.

  • fast/js/global-recursion-on-full-stack.html:
File size: 6.1 KB
Line 
1/*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config.h"
30#include "JSActivation.h"
31
32#include "Arguments.h"
33#include "Interpreter.h"
34#include "JSFunction.h"
35
36namespace JSC {
37
38ASSERT_CLASS_FITS_IN_CELL(JSActivation);
39
40const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
41
42JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionBodyNode> functionBody)
43 : Base(callFrame->globalData().activationStructure, new JSActivationData(functionBody, callFrame->registers()))
44{
45}
46
47JSActivation::~JSActivation()
48{
49 delete d();
50}
51
52void JSActivation::mark()
53{
54 Base::mark();
55
56 Register* registerArray = d()->registerArray.get();
57 if (!registerArray)
58 return;
59
60 size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
61
62 size_t i = 0;
63 size_t count = numParametersMinusThis;
64 for ( ; i < count; ++i) {
65 Register& r = registerArray[i];
66 if (!r.marked())
67 r.mark();
68 }
69
70 size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
71
72 // Skip the call frame, which sits between the parameters and vars.
73 i += RegisterFile::CallFrameHeaderSize;
74 count += RegisterFile::CallFrameHeaderSize + numVars;
75
76 for ( ; i < count; ++i) {
77 Register& r = registerArray[i];
78 if (r.jsValue() && !r.marked())
79 r.mark();
80 }
81}
82
83bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
84{
85 if (symbolTableGet(propertyName, slot))
86 return true;
87
88 if (JSValue* location = getDirectLocation(propertyName)) {
89 slot.setValueSlot(location);
90 return true;
91 }
92
93 // Only return the built-in arguments object if it wasn't overridden above.
94 if (propertyName == exec->propertyNames().arguments) {
95 slot.setCustom(this, getArgumentsGetter());
96 return true;
97 }
98
99 // We don't call through to JSObject because there's no way to give an
100 // activation object getter properties or a prototype.
101 ASSERT(!hasGetterSetterProperties());
102 ASSERT(prototype().isNull());
103 return false;
104}
105
106void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
107{
108 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
109
110 if (symbolTablePut(propertyName, value))
111 return;
112
113 // We don't call through to JSObject because __proto__ and getter/setter
114 // properties are non-standard extensions that other implementations do not
115 // expose in the activation object.
116 ASSERT(!hasGetterSetterProperties());
117 putDirect(propertyName, value, 0, true, slot);
118}
119
120// FIXME: Make this function honor ReadOnly (const) and DontEnum
121void JSActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
122{
123 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
124
125 if (symbolTablePutWithAttributes(propertyName, value, attributes))
126 return;
127
128 // We don't call through to JSObject because __proto__ and getter/setter
129 // properties are non-standard extensions that other implementations do not
130 // expose in the activation object.
131 ASSERT(!hasGetterSetterProperties());
132 PutPropertySlot slot;
133 JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot);
134}
135
136bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName)
137{
138 if (propertyName == exec->propertyNames().arguments)
139 return false;
140
141 return Base::deleteProperty(exec, propertyName);
142}
143
144JSObject* JSActivation::toThisObject(ExecState* exec) const
145{
146 return exec->globalThisValue();
147}
148
149bool JSActivation::isDynamicScope() const
150{
151 return d()->functionBody->usesEval();
152}
153
154JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
155{
156 JSActivation* activation = asActivation(slot.slotBase());
157
158 if (activation->d()->functionBody->usesArguments()) {
159 PropertySlot slot;
160 activation->symbolTableGet(exec->propertyNames().arguments, slot);
161 return slot.getValue(exec, exec->propertyNames().arguments);
162 }
163
164 CallFrame* callFrame = CallFrame::create(activation->d()->registers);
165 Arguments* arguments = callFrame->optionalCalleeArguments();
166 if (!arguments) {
167 arguments = new (callFrame) Arguments(callFrame);
168 arguments->copyRegisters();
169 callFrame->setCalleeArguments(arguments);
170 }
171 ASSERT(arguments->isObject(&Arguments::info));
172
173 return arguments;
174}
175
176// These two functions serve the purpose of isolating the common case from a
177// PIC branch.
178
179PropertySlot::GetValueFunc JSActivation::getArgumentsGetter()
180{
181 return argumentsGetter;
182}
183
184} // namespace JSC
Note: See TracBrowser for help on using the repository browser.