source: webkit/trunk/JavaScriptCore/kjs/nodes.cpp@ 37433

Last change on this file since 37433 was 37433, checked in by Darin Adler, 17 years ago

JavaScriptCore:

2008-10-08 Darin Adler <Darin Adler>

Reviewed by Cameron Zwarich.

Add CallFrame as a synonym for ExecState. Arguably, some day we should switch every
client over to the new name.

Use CallFrame* consistently rather than Register* or ExecState* in low-level code such
as Machine.cpp and CTI.cpp. Similarly, use callFrame rather than r as its name and use
accessor functions to get at things in the frame.

Eliminate other uses of ExecState* that aren't needed, replacing in some cases with
JSGlobalData* and in other cases eliminating them entirely.

  • API/JSObjectRef.cpp: (JSObjectMakeFunctionWithCallback): (JSObjectMakeFunction): (JSObjectHasProperty): (JSObjectGetProperty): (JSObjectSetProperty): (JSObjectDeleteProperty):
  • API/OpaqueJSString.cpp:
  • API/OpaqueJSString.h:
  • VM/CTI.cpp: (JSC::CTI::getConstant): (JSC::CTI::emitGetArg): (JSC::CTI::emitGetPutArg): (JSC::CTI::getConstantImmediateNumericArg): (JSC::CTI::printOpcodeOperandTypes): (JSC::CTI::CTI): (JSC::CTI::compileOpCall): (JSC::CTI::compileBinaryArithOp): (JSC::CTI::privateCompileMainPass): (JSC::CTI::privateCompile): (JSC::CTI::privateCompileGetByIdProto): (JSC::CTI::privateCompileGetByIdChain): (JSC::CTI::compileRegExp):
  • VM/CTI.h:
  • VM/CodeBlock.h:
  • VM/CodeGenerator.cpp: (JSC::CodeGenerator::emitEqualityOp): (JSC::CodeGenerator::emitLoad): (JSC::CodeGenerator::emitUnexpectedLoad): (JSC::CodeGenerator::emitConstruct):
  • VM/CodeGenerator.h:
  • VM/Machine.cpp: (JSC::jsLess): (JSC::jsLessEq): (JSC::jsAddSlowCase): (JSC::jsAdd): (JSC::jsTypeStringForValue): (JSC::Machine::resolve): (JSC::Machine::resolveSkip): (JSC::Machine::resolveGlobal): (JSC::inlineResolveBase): (JSC::Machine::resolveBase): (JSC::Machine::resolveBaseAndProperty): (JSC::Machine::resolveBaseAndFunc): (JSC::Machine::slideRegisterWindowForCall): (JSC::isNotObject): (JSC::Machine::callEval): (JSC::Machine::dumpCallFrame): (JSC::Machine::dumpRegisters): (JSC::Machine::unwindCallFrame): (JSC::Machine::throwException): (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): (JSC::DynamicGlobalObjectScope::~DynamicGlobalObjectScope): (JSC::Machine::execute): (JSC::Machine::debug): (JSC::Machine::createExceptionScope): (JSC::cachePrototypeChain): (JSC::Machine::tryCachePutByID): (JSC::Machine::tryCacheGetByID): (JSC::Machine::privateExecute): (JSC::Machine::retrieveArguments): (JSC::Machine::retrieveCaller): (JSC::Machine::retrieveLastCaller): (JSC::Machine::findFunctionCallFrame): (JSC::Machine::getArgumentsData): (JSC::Machine::tryCTICachePutByID): (JSC::Machine::getCTIArrayLengthTrampoline): (JSC::Machine::getCTIStringLengthTrampoline): (JSC::Machine::tryCTICacheGetByID): (JSC::Machine::cti_op_convert_this): (JSC::Machine::cti_op_end): (JSC::Machine::cti_op_add): (JSC::Machine::cti_op_pre_inc): (JSC::Machine::cti_timeout_check): (JSC::Machine::cti_op_loop_if_less): (JSC::Machine::cti_op_loop_if_lesseq): (JSC::Machine::cti_op_new_object): (JSC::Machine::cti_op_put_by_id): (JSC::Machine::cti_op_put_by_id_second): (JSC::Machine::cti_op_put_by_id_generic): (JSC::Machine::cti_op_put_by_id_fail): (JSC::Machine::cti_op_get_by_id): (JSC::Machine::cti_op_get_by_id_second): (JSC::Machine::cti_op_get_by_id_generic): (JSC::Machine::cti_op_get_by_id_fail): (JSC::Machine::cti_op_instanceof): (JSC::Machine::cti_op_del_by_id): (JSC::Machine::cti_op_mul): (JSC::Machine::cti_op_new_func): (JSC::Machine::cti_op_call_JSFunction): (JSC::Machine::cti_vm_compile): (JSC::Machine::cti_op_push_activation): (JSC::Machine::cti_op_call_NotJSFunction): (JSC::Machine::cti_op_create_arguments): (JSC::Machine::cti_op_tear_off_activation): (JSC::Machine::cti_op_tear_off_arguments): (JSC::Machine::cti_op_ret_profiler): (JSC::Machine::cti_op_ret_scopeChain): (JSC::Machine::cti_op_new_array): (JSC::Machine::cti_op_resolve): (JSC::Machine::cti_op_construct_JSConstruct): (JSC::Machine::cti_op_construct_NotJSConstruct): (JSC::Machine::cti_op_get_by_val): (JSC::Machine::cti_op_resolve_func): (JSC::Machine::cti_op_sub): (JSC::Machine::cti_op_put_by_val): (JSC::Machine::cti_op_put_by_val_array): (JSC::Machine::cti_op_lesseq): (JSC::Machine::cti_op_loop_if_true): (JSC::Machine::cti_op_negate): (JSC::Machine::cti_op_resolve_base): (JSC::Machine::cti_op_resolve_skip): (JSC::Machine::cti_op_resolve_global): (JSC::Machine::cti_op_div): (JSC::Machine::cti_op_pre_dec): (JSC::Machine::cti_op_jless): (JSC::Machine::cti_op_not): (JSC::Machine::cti_op_jtrue): (JSC::Machine::cti_op_post_inc): (JSC::Machine::cti_op_eq): (JSC::Machine::cti_op_lshift): (JSC::Machine::cti_op_bitand): (JSC::Machine::cti_op_rshift): (JSC::Machine::cti_op_bitnot): (JSC::Machine::cti_op_resolve_with_base): (JSC::Machine::cti_op_new_func_exp): (JSC::Machine::cti_op_mod): (JSC::Machine::cti_op_less): (JSC::Machine::cti_op_neq): (JSC::Machine::cti_op_post_dec): (JSC::Machine::cti_op_urshift): (JSC::Machine::cti_op_bitxor): (JSC::Machine::cti_op_new_regexp): (JSC::Machine::cti_op_bitor): (JSC::Machine::cti_op_call_eval): (JSC::Machine::cti_op_throw): (JSC::Machine::cti_op_get_pnames): (JSC::Machine::cti_op_next_pname): (JSC::Machine::cti_op_push_scope): (JSC::Machine::cti_op_pop_scope): (JSC::Machine::cti_op_typeof): (JSC::Machine::cti_op_to_jsnumber): (JSC::Machine::cti_op_in): (JSC::Machine::cti_op_push_new_scope): (JSC::Machine::cti_op_jmp_scopes): (JSC::Machine::cti_op_put_by_index): (JSC::Machine::cti_op_switch_imm): (JSC::Machine::cti_op_switch_char): (JSC::Machine::cti_op_switch_string): (JSC::Machine::cti_op_del_by_val): (JSC::Machine::cti_op_put_getter): (JSC::Machine::cti_op_put_setter): (JSC::Machine::cti_op_new_error): (JSC::Machine::cti_op_debug): (JSC::Machine::cti_vm_throw):
  • VM/Machine.h:
  • VM/Register.h:
  • VM/RegisterFile.h:
  • kjs/Arguments.h:
  • kjs/DebuggerCallFrame.cpp: (JSC::DebuggerCallFrame::functionName): (JSC::DebuggerCallFrame::type): (JSC::DebuggerCallFrame::thisObject): (JSC::DebuggerCallFrame::evaluate):
  • kjs/DebuggerCallFrame.h:
  • kjs/ExecState.cpp: (JSC::CallFrame::thisValue):
  • kjs/ExecState.h:
  • kjs/FunctionConstructor.cpp: (JSC::constructFunction):
  • kjs/JSActivation.cpp: (JSC::JSActivation::JSActivation): (JSC::JSActivation::argumentsGetter):
  • kjs/JSActivation.h:
  • kjs/JSGlobalObject.cpp: (JSC::JSGlobalObject::init):
  • kjs/JSGlobalObjectFunctions.cpp: (JSC::globalFuncEval):
  • kjs/JSVariableObject.h:
  • kjs/Parser.cpp: (JSC::Parser::parse):
  • kjs/RegExpConstructor.cpp: (JSC::constructRegExp):
  • kjs/RegExpPrototype.cpp: (JSC::regExpProtoFuncCompile):
  • kjs/Shell.cpp: (prettyPrintScript):
  • kjs/StringPrototype.cpp: (JSC::stringProtoFuncMatch): (JSC::stringProtoFuncSearch):
  • kjs/identifier.cpp: (JSC::Identifier::checkSameIdentifierTable):
  • kjs/interpreter.cpp: (JSC::Interpreter::checkSyntax): (JSC::Interpreter::evaluate):
  • kjs/nodes.cpp: (JSC::ThrowableExpressionData::emitThrowError): (JSC::RegExpNode::emitCode): (JSC::ArrayNode::emitCode): (JSC::InstanceOfNode::emitCode):
  • kjs/nodes.h:
  • kjs/regexp.cpp: (JSC::RegExp::RegExp): (JSC::RegExp::create):
  • kjs/regexp.h:
  • profiler/HeavyProfile.h:
  • profiler/Profile.h:
  • wrec/WREC.cpp:
  • wrec/WREC.h:

WebKit/mac:

2008-10-08 Darin Adler <Darin Adler>

Reviewed by Cameron Zwarich.

  • WebView/WebScriptDebugger.mm: (WebScriptDebugger::WebScriptDebugger): Update since DebuggerCallFrame is simpler now.
  • Property svn:eol-style set to native
File size: 76.3 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 Apple Inc. All rights reserved.
5* Copyright (C) 2007 Cameron Zwarich ([email protected])
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <[email protected]>
8*
9* This library is free software; you can redistribute it and/or
10* modify it under the terms of the GNU Library General Public
11* License as published by the Free Software Foundation; either
12* version 2 of the License, or (at your option) any later version.
13*
14* This library is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17* Library General Public License for more details.
18*
19* You should have received a copy of the GNU Library General Public License
20* along with this library; see the file COPYING.LIB. If not, write to
21* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22* Boston, MA 02110-1301, USA.
23*
24*/
25
26#include "config.h"
27#include "nodes.h"
28
29#include "CodeGenerator.h"
30#include "ExecState.h"
31#include "JSGlobalObject.h"
32#include "JSStaticScopeObject.h"
33#include "Parser.h"
34#include "PropertyNameArray.h"
35#include "RegExpObject.h"
36#include "debugger.h"
37#include "lexer.h"
38#include "operations.h"
39#include "SamplingTool.h"
40#include <math.h>
41#include <wtf/Assertions.h>
42#include <wtf/HashCountedSet.h>
43#include <wtf/HashSet.h>
44#include <wtf/MathExtras.h>
45#include <wtf/RefCountedLeakCounter.h>
46#include <wtf/Threading.h>
47
48using namespace WTF;
49
50namespace JSC {
51
52// ------------------------------ Node -----------------------------------------
53
54#ifndef NDEBUG
55static RefCountedLeakCounter parserRefCountedCounter("JSC::Node");
56#endif
57
58ParserRefCounted::ParserRefCounted(JSGlobalData* globalData)
59 : m_globalData(globalData)
60{
61#ifndef NDEBUG
62 parserRefCountedCounter.increment();
63#endif
64 if (!m_globalData->newParserObjects)
65 m_globalData->newParserObjects = new HashSet<ParserRefCounted*>;
66 m_globalData->newParserObjects->add(this);
67 ASSERT(m_globalData->newParserObjects->contains(this));
68}
69
70ParserRefCounted::~ParserRefCounted()
71{
72#ifndef NDEBUG
73 parserRefCountedCounter.decrement();
74#endif
75}
76
77void ParserRefCounted::ref()
78{
79 // bumping from 0 to 1 is just removing from the new nodes set
80 if (m_globalData->newParserObjects) {
81 HashSet<ParserRefCounted*>::iterator it = m_globalData->newParserObjects->find(this);
82 if (it != m_globalData->newParserObjects->end()) {
83 m_globalData->newParserObjects->remove(it);
84 ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
85 return;
86 }
87 }
88
89 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
90
91 if (!m_globalData->parserObjectExtraRefCounts)
92 m_globalData->parserObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
93 m_globalData->parserObjectExtraRefCounts->add(this);
94}
95
96void ParserRefCounted::deref()
97{
98 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
99
100 if (!m_globalData->parserObjectExtraRefCounts) {
101 delete this;
102 return;
103 }
104
105 HashCountedSet<ParserRefCounted*>::iterator it = m_globalData->parserObjectExtraRefCounts->find(this);
106 if (it == m_globalData->parserObjectExtraRefCounts->end())
107 delete this;
108 else
109 m_globalData->parserObjectExtraRefCounts->remove(it);
110}
111
112bool ParserRefCounted::hasOneRef()
113{
114 if (m_globalData->newParserObjects && m_globalData->newParserObjects->contains(this)) {
115 ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
116 return false;
117 }
118
119 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
120
121 if (!m_globalData->parserObjectExtraRefCounts)
122 return true;
123
124 return !m_globalData->parserObjectExtraRefCounts->contains(this);
125}
126
127void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData)
128{
129 if (!globalData->newParserObjects)
130 return;
131
132#ifndef NDEBUG
133 HashSet<ParserRefCounted*>::iterator end = globalData->newParserObjects->end();
134 for (HashSet<ParserRefCounted*>::iterator it = globalData->newParserObjects->begin(); it != end; ++it)
135 ASSERT(!globalData->parserObjectExtraRefCounts || !globalData->parserObjectExtraRefCounts->contains(*it));
136#endif
137 deleteAllValues(*globalData->newParserObjects);
138 delete globalData->newParserObjects;
139 globalData->newParserObjects = 0;
140}
141
142Node::Node(JSGlobalData* globalData)
143 : ParserRefCounted(globalData)
144{
145 m_line = globalData->lexer->lineNo();
146}
147
148static void substitute(UString& string, const UString& substring) JSC_FAST_CALL;
149static void substitute(UString& string, const UString& substring)
150{
151 int position = string.find("%s");
152 ASSERT(position != -1);
153 UString newString = string.substr(0, position);
154 newString.append(substring);
155 newString.append(string.substr(position + 2));
156 string = newString;
157}
158
159RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg)
160{
161 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
162 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg));
163 generator.emitThrow(exception);
164 return exception;
165}
166
167RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
168{
169 UString message = msg;
170 substitute(message, label.ustring());
171 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
172 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), message));
173 generator.emitThrow(exception);
174 return exception;
175}
176
177// ------------------------------ StatementNode --------------------------------
178
179StatementNode::StatementNode(JSGlobalData* globalData)
180 : Node(globalData)
181 , m_lastLine(-1)
182{
183}
184
185void StatementNode::setLoc(int firstLine, int lastLine)
186{
187 m_line = firstLine;
188 m_lastLine = lastLine;
189}
190
191// ------------------------------ SourceElements --------------------------------
192
193void SourceElements::append(PassRefPtr<StatementNode> statement)
194{
195 if (statement->isEmptyStatement())
196 return;
197
198 m_statements.append(statement);
199}
200
201// ------------------------------ NullNode -------------------------------------
202
203RegisterID* NullNode::emitCode(CodeGenerator& generator, RegisterID* dst)
204{
205 if (dst == ignoredResult())
206 return 0;
207 return generator.emitLoad(dst, jsNull());
208}
209
210// ------------------------------ BooleanNode ----------------------------------
211
212RegisterID* BooleanNode::emitCode(CodeGenerator& generator, RegisterID* dst)
213{
214 if (dst == ignoredResult())
215 return 0;
216 return generator.emitLoad(dst, m_value);
217}
218
219// ------------------------------ NumberNode -----------------------------------
220
221RegisterID* NumberNode::emitCode(CodeGenerator& generator, RegisterID* dst)
222{
223 if (dst == ignoredResult())
224 return 0;
225 return generator.emitLoad(dst, m_double);
226}
227
228// ------------------------------ StringNode -----------------------------------
229
230RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst)
231{
232 if (dst == ignoredResult())
233 return 0;
234 return generator.emitLoad(dst, m_value);
235}
236
237// ------------------------------ RegExpNode -----------------------------------
238
239RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
240{
241 RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags);
242 if (!regExp->isValid())
243 return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
244 if (dst == ignoredResult())
245 return 0;
246 return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
247}
248
249// ------------------------------ ThisNode -------------------------------------
250
251RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
252{
253 if (dst == ignoredResult())
254 return 0;
255 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
256}
257
258// ------------------------------ ResolveNode ----------------------------------
259
260bool ResolveNode::isPure(CodeGenerator& generator) const
261{
262 return generator.isLocal(m_ident);
263}
264
265RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
266{
267 if (RegisterID* local = generator.registerFor(m_ident)) {
268 if (dst == ignoredResult())
269 return 0;
270 return generator.moveToDestinationIfNeeded(dst, local);
271 }
272
273 generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
274 return generator.emitResolve(generator.finalDestination(dst), m_ident);
275}
276
277// ------------------------------ ArrayNode ------------------------------------
278
279RegisterID* ArrayNode::emitCode(CodeGenerator& generator, RegisterID* dst)
280{
281 // FIXME: Should we put all of this code into emitNewArray?
282
283 unsigned length = 0;
284 ElementNode* firstPutElement;
285 for (firstPutElement = m_element.get(); firstPutElement; firstPutElement = firstPutElement->next()) {
286 if (firstPutElement->elision())
287 break;
288 ++length;
289 }
290
291 if (!firstPutElement && !m_elision)
292 return generator.emitNewArray(generator.finalDestination(dst), m_element.get());
293
294 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element.get());
295
296 for (ElementNode* n = firstPutElement; n; n = n->next()) {
297 RegisterID* value = generator.emitNode(n->value());
298 length += n->elision();
299 generator.emitPutByIndex(array.get(), length++, value);
300 }
301
302 if (m_elision) {
303 RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length));
304 generator.emitPutById(array.get(), generator.propertyNames().length, value);
305 }
306
307 return generator.moveToDestinationIfNeeded(dst, array.get());
308}
309
310// ------------------------------ ObjectLiteralNode ----------------------------
311
312RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* dst)
313{
314 if (!m_list) {
315 if (dst == ignoredResult())
316 return 0;
317 return generator.emitNewObject(generator.finalDestination(dst));
318 }
319 return generator.emitNode(dst, m_list.get());
320}
321
322// ------------------------------ PropertyListNode -----------------------------
323
324RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
325{
326 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
327
328 generator.emitNewObject(newObj.get());
329
330 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
331 RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
332
333 switch (p->m_node->m_type) {
334 case PropertyNode::Constant: {
335 generator.emitPutById(newObj.get(), p->m_node->name(), value);
336 break;
337 }
338 case PropertyNode::Getter: {
339 generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
340 break;
341 }
342 case PropertyNode::Setter: {
343 generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
344 break;
345 }
346 default:
347 ASSERT_NOT_REACHED();
348 }
349 }
350
351 return generator.moveToDestinationIfNeeded(dst, newObj.get());
352}
353
354// ------------------------------ BracketAccessorNode --------------------------------
355
356RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
357{
358 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator));
359 RegisterID* property = generator.emitNode(m_subscript.get());
360 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
361 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
362}
363
364// ------------------------------ DotAccessorNode --------------------------------
365
366RegisterID* DotAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
367{
368 RegisterID* base = generator.emitNode(m_base.get());
369 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
370 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
371}
372
373// ------------------------------ ArgumentListNode -----------------------------
374
375RegisterID* ArgumentListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
376{
377 ASSERT(m_expr);
378 return generator.emitNode(dst, m_expr.get());
379}
380
381// ------------------------------ NewExprNode ----------------------------------
382
383RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
384{
385 RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
386 return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
387}
388
389RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
390{
391 RefPtr<RegisterID> base = generator.tempDestination(dst);
392 RefPtr<RegisterID> func = generator.newTemporary();
393 generator.emitResolveWithBase(base.get(), func.get(), generator.propertyNames().eval);
394 return generator.emitCallEval(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
395}
396
397RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
398{
399 RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
400 return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
401}
402
403RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
404{
405 if (RefPtr<RegisterID> local = generator.registerFor(m_ident))
406 return generator.emitCall(generator.finalDestination(dst), local.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
407
408 int index = 0;
409 size_t depth = 0;
410 JSValue* globalObject = 0;
411 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
412 RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
413 return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
414 }
415
416 RefPtr<RegisterID> base = generator.tempDestination(dst);
417 RefPtr<RegisterID> func = generator.newTemporary();
418 int identifierStart = m_divot - m_startOffset;
419 generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
420 generator.emitResolveFunction(base.get(), func.get(), m_ident);
421 return generator.emitCall(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
422}
423
424RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
425{
426 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
427 RegisterID* property = generator.emitNode(m_subscript.get());
428 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
429 RefPtr<RegisterID> function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
430 return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
431}
432
433RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
434{
435 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
436 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
437 RefPtr<RegisterID> function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
438 return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
439}
440
441// ------------------------------ PostfixResolveNode ----------------------------------
442
443static RegisterID* emitPreIncOrDec(CodeGenerator& generator, RegisterID* srcDst, Operator oper)
444{
445 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
446}
447
448static RegisterID* emitPostIncOrDec(CodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
449{
450 return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
451}
452
453RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
454{
455 if (RegisterID* local = generator.registerFor(m_ident)) {
456 if (generator.isLocalConstant(m_ident)) {
457 if (dst == ignoredResult())
458 return 0;
459 return generator.emitToJSNumber(generator.finalDestination(dst), local);
460 }
461
462 if (dst == ignoredResult())
463 return emitPreIncOrDec(generator, local, m_operator);
464 return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
465 }
466
467 int index = 0;
468 size_t depth = 0;
469 JSValue* globalObject = 0;
470 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
471 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
472 RegisterID* oldValue;
473 if (dst == ignoredResult()) {
474 oldValue = 0;
475 emitPreIncOrDec(generator, value.get(), m_operator);
476 } else {
477 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
478 }
479 generator.emitPutScopedVar(depth, index, value.get(), globalObject);
480 return oldValue;
481 }
482
483 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
484 RefPtr<RegisterID> value = generator.newTemporary();
485 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
486 RegisterID* oldValue;
487 if (dst == ignoredResult()) {
488 oldValue = 0;
489 emitPreIncOrDec(generator, value.get(), m_operator);
490 } else {
491 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
492 }
493 generator.emitPutById(base.get(), m_ident, value.get());
494 return oldValue;
495}
496
497// ------------------------------ PostfixBracketNode ----------------------------------
498
499RegisterID* PostfixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
500{
501 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
502 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
503
504 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
505 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
506 RegisterID* oldValue;
507 if (dst == ignoredResult()) {
508 oldValue = 0;
509 if (m_operator == OpPlusPlus)
510 generator.emitPreInc(value.get());
511 else
512 generator.emitPreDec(value.get());
513 } else {
514 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
515 }
516 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
517 generator.emitPutByVal(base.get(), property.get(), value.get());
518 return oldValue;
519}
520
521// ------------------------------ PostfixDotNode ----------------------------------
522
523RegisterID* PostfixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
524{
525 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
526
527 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
528 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
529 RegisterID* oldValue;
530 if (dst == ignoredResult()) {
531 oldValue = 0;
532 if (m_operator == OpPlusPlus)
533 generator.emitPreInc(value.get());
534 else
535 generator.emitPreDec(value.get());
536 } else {
537 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
538 }
539 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
540 generator.emitPutById(base.get(), m_ident, value.get());
541 return oldValue;
542}
543
544// ------------------------------ PostfixErrorNode -----------------------------------
545
546RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
547{
548 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference.");
549}
550
551// ------------------------------ DeleteResolveNode -----------------------------------
552
553RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
554{
555 if (generator.registerFor(m_ident))
556 return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
557
558 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
559 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
560 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
561}
562
563// ------------------------------ DeleteBracketNode -----------------------------------
564
565RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
566{
567 RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
568 RegisterID* r1 = generator.emitNode(m_subscript.get());
569
570 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
571 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
572}
573
574// ------------------------------ DeleteDotNode -----------------------------------
575
576RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
577{
578 RegisterID* r0 = generator.emitNode(m_base.get());
579
580 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
581 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
582}
583
584// ------------------------------ DeleteValueNode -----------------------------------
585
586RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
587{
588 generator.emitNode(ignoredResult(), m_expr.get());
589
590 // delete on a non-location expression ignores the value and returns true
591 return generator.emitUnexpectedLoad(generator.finalDestination(dst), true);
592}
593
594// ------------------------------ VoidNode -------------------------------------
595
596RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
597{
598 if (dst == ignoredResult()) {
599 generator.emitNode(ignoredResult(), m_expr.get());
600 return 0;
601 }
602 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
603 return generator.emitLoad(dst, jsUndefined());
604}
605
606// ------------------------------ TypeOfValueNode -----------------------------------
607
608RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
609{
610 if (RegisterID* local = generator.registerFor(m_ident)) {
611 if (dst == ignoredResult())
612 return 0;
613 return generator.emitTypeOf(generator.finalDestination(dst), local);
614 }
615
616 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
617 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
618 if (dst == ignoredResult())
619 return 0;
620 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
621}
622
623// ------------------------------ TypeOfValueNode -----------------------------------
624
625RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
626{
627 if (dst == ignoredResult()) {
628 generator.emitNode(ignoredResult(), m_expr.get());
629 return 0;
630 }
631 RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
632 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
633}
634
635// ------------------------------ PrefixResolveNode ----------------------------------
636
637RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
638{
639 if (RegisterID* local = generator.registerFor(m_ident)) {
640 if (generator.isLocalConstant(m_ident)) {
641 if (dst == ignoredResult())
642 return 0;
643 RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
644 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
645 }
646
647 emitPreIncOrDec(generator, local, m_operator);
648 return generator.moveToDestinationIfNeeded(dst, local);
649 }
650
651 int index = 0;
652 size_t depth = 0;
653 JSValue* globalObject = 0;
654 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
655 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
656 emitPreIncOrDec(generator, propDst.get(), m_operator);
657 generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
658 return generator.moveToDestinationIfNeeded(dst, propDst.get());
659 }
660
661 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
662 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
663 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
664 emitPreIncOrDec(generator, propDst.get(), m_operator);
665 generator.emitPutById(base.get(), m_ident, propDst.get());
666 return generator.moveToDestinationIfNeeded(dst, propDst.get());
667}
668
669// ------------------------------ PrefixBracketNode ----------------------------------
670
671RegisterID* PrefixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
672{
673 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
674 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
675 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
676
677 generator.emitExpressionInfo(m_divot + m_subexpressionDivotOffset, m_subexpressionStartOffset, m_endOffset - m_subexpressionDivotOffset);
678 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
679 if (m_operator == OpPlusPlus)
680 generator.emitPreInc(value);
681 else
682 generator.emitPreDec(value);
683 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
684 generator.emitPutByVal(base.get(), property.get(), value);
685 return generator.moveToDestinationIfNeeded(dst, propDst.get());
686}
687
688// ------------------------------ PrefixDotNode ----------------------------------
689
690RegisterID* PrefixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
691{
692 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
693 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
694
695 generator.emitExpressionInfo(m_divot + m_subexpressionDivotOffset, m_subexpressionStartOffset, m_endOffset - m_subexpressionDivotOffset);
696 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
697 if (m_operator == OpPlusPlus)
698 generator.emitPreInc(value);
699 else
700 generator.emitPreDec(value);
701 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
702 generator.emitPutById(base.get(), m_ident, value);
703 return generator.moveToDestinationIfNeeded(dst, propDst.get());
704}
705
706// ------------------------------ PrefixErrorNode -----------------------------------
707
708RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
709{
710 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference.");
711}
712
713// ------------------------------ Unary Operation Nodes -----------------------------------
714
715RegisterID* UnaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
716{
717 RegisterID* src = generator.emitNode(m_expr.get());
718 return generator.emitUnaryOp(opcode(), generator.finalDestination(dst), src);
719}
720
721// ------------------------------ Binary Operation Nodes -----------------------------------
722
723RegisterID* BinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
724{
725 OpcodeID opcode = this->opcode();
726 if (opcode == op_neq) {
727 if (m_expr1->isNull() || m_expr2->isNull()) {
728 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
729 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
730 }
731 }
732
733 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
734 RegisterID* src2 = generator.emitNode(m_expr2.get());
735 return generator.emitBinaryOp(opcode, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
736}
737
738RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
739{
740 if (m_expr1->isNull() || m_expr2->isNull()) {
741 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
742 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
743 }
744
745 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
746 RegisterID* src2 = generator.emitNode(m_expr2.get());
747 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
748}
749
750RegisterID* StrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
751{
752 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
753 RegisterID* src2 = generator.emitNode(m_expr2.get());
754 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
755}
756
757RegisterID* ReverseBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
758{
759 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
760 RegisterID* src2 = generator.emitNode(m_expr2.get());
761 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
762}
763
764RegisterID* ThrowableBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
765{
766 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
767 RegisterID* src2 = generator.emitNode(m_expr2.get());
768 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
769 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
770}
771
772RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
773{
774 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
775 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
776
777 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
778 RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
779
780 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
781 return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
782}
783
784// ------------------------------ Binary Logical Nodes ----------------------------
785
786RegisterID* LogicalOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
787{
788 RefPtr<RegisterID> temp = generator.tempDestination(dst);
789 RefPtr<LabelID> target = generator.newLabel();
790
791 generator.emitNode(temp.get(), m_expr1.get());
792 if (m_operator == OpLogicalAnd)
793 generator.emitJumpIfFalse(temp.get(), target.get());
794 else
795 generator.emitJumpIfTrue(temp.get(), target.get());
796 generator.emitNode(temp.get(), m_expr2.get());
797 generator.emitLabel(target.get());
798
799 return generator.moveToDestinationIfNeeded(dst, temp.get());
800}
801
802// ------------------------------ ConditionalNode ------------------------------
803
804RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst)
805{
806 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
807 RefPtr<LabelID> beforeElse = generator.newLabel();
808 RefPtr<LabelID> afterElse = generator.newLabel();
809
810 RegisterID* cond = generator.emitNode(m_logical.get());
811 generator.emitJumpIfFalse(cond, beforeElse.get());
812
813 generator.emitNode(newDst.get(), m_expr1.get());
814 generator.emitJump(afterElse.get());
815
816 generator.emitLabel(beforeElse.get());
817 generator.emitNode(newDst.get(), m_expr2.get());
818
819 generator.emitLabel(afterElse.get());
820
821 return newDst.get();
822}
823
824// ------------------------------ ReadModifyResolveNode -----------------------------------
825
826// FIXME: should this be moved to be a method on CodeGenerator?
827static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types)
828{
829 OpcodeID opcode;
830 switch (oper) {
831 case OpMultEq:
832 opcode = op_mul;
833 break;
834 case OpDivEq:
835 opcode = op_div;
836 break;
837 case OpPlusEq:
838 opcode = op_add;
839 break;
840 case OpMinusEq:
841 opcode = op_sub;
842 break;
843 case OpLShift:
844 opcode = op_lshift;
845 break;
846 case OpRShift:
847 opcode = op_rshift;
848 break;
849 case OpURShift:
850 opcode = op_urshift;
851 break;
852 case OpAndEq:
853 opcode = op_bitand;
854 break;
855 case OpXOrEq:
856 opcode = op_bitxor;
857 break;
858 case OpOrEq:
859 opcode = op_bitor;
860 break;
861 case OpModEq:
862 opcode = op_mod;
863 break;
864 default:
865 ASSERT_NOT_REACHED();
866 return dst;
867 }
868
869 return generator.emitBinaryOp(opcode, dst, src1, src2, types);
870}
871
872RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
873{
874 if (RegisterID* local = generator.registerFor(m_ident)) {
875 if (generator.isLocalConstant(m_ident)) {
876 RegisterID* src2 = generator.emitNode(m_right.get());
877 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
878 }
879
880 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
881 RefPtr<RegisterID> result = generator.newTemporary();
882 generator.emitMove(result.get(), local);
883 RegisterID* src2 = generator.emitNode(m_right.get());
884 emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
885 generator.emitMove(local, result.get());
886 return generator.moveToDestinationIfNeeded(dst, result.get());
887 }
888
889 RegisterID* src2 = generator.emitNode(m_right.get());
890 RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
891 return generator.moveToDestinationIfNeeded(dst, result);
892 }
893
894 int index = 0;
895 size_t depth = 0;
896 JSValue* globalObject = 0;
897 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
898 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
899 RegisterID* src2 = generator.emitNode(m_right.get());
900 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
901 generator.emitPutScopedVar(depth, index, result, globalObject);
902 return result;
903 }
904
905 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
906 generator.emitExpressionInfo(m_divot - m_startOffset + m_ident.size(), m_ident.size(), 0);
907 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
908 RegisterID* src2 = generator.emitNode(m_right.get());
909 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
910 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
911 return generator.emitPutById(base.get(), m_ident, result);
912}
913
914// ------------------------------ AssignResolveNode -----------------------------------
915
916RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
917{
918 if (RegisterID* local = generator.registerFor(m_ident)) {
919 if (generator.isLocalConstant(m_ident))
920 return generator.emitNode(dst, m_right.get());
921
922 RegisterID* result = generator.emitNode(local, m_right.get());
923 return generator.moveToDestinationIfNeeded(dst, result);
924 }
925
926 int index = 0;
927 size_t depth = 0;
928 JSValue* globalObject = 0;
929 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
930 if (dst == ignoredResult())
931 dst = 0;
932 RegisterID* value = generator.emitNode(dst, m_right.get());
933 generator.emitPutScopedVar(depth, index, value, globalObject);
934 return value;
935 }
936
937 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
938 if (dst == ignoredResult())
939 dst = 0;
940 RegisterID* value = generator.emitNode(dst, m_right.get());
941 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
942 return generator.emitPutById(base.get(), m_ident, value);
943}
944
945// ------------------------------ AssignDotNode -----------------------------------
946
947RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
948{
949 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
950 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
951 RegisterID* result = generator.emitNode(value.get(), m_right.get());
952 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
953 generator.emitPutById(base.get(), m_ident, result);
954 return generator.moveToDestinationIfNeeded(dst, result);
955}
956
957// ------------------------------ ReadModifyDotNode -----------------------------------
958
959RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
960{
961 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
962
963 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
964 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
965 RegisterID* change = generator.emitNode(m_right.get());
966 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
967
968 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
969 return generator.emitPutById(base.get(), m_ident, updatedValue);
970}
971
972// ------------------------------ AssignErrorNode -----------------------------------
973
974RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
975{
976 return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
977}
978
979// ------------------------------ AssignBracketNode -----------------------------------
980
981RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
982{
983 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
984 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
985 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
986 RegisterID* result = generator.emitNode(value.get(), m_right.get());
987
988 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
989 generator.emitPutByVal(base.get(), property.get(), result);
990 return generator.moveToDestinationIfNeeded(dst, result);
991}
992
993RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
994{
995 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
996 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
997
998 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
999 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1000 RegisterID* change = generator.emitNode(m_right.get());
1001 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1002
1003 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1004 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1005
1006 return updatedValue;
1007}
1008
1009// ------------------------------ CommaNode ------------------------------------
1010
1011RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1012{
1013 generator.emitNode(ignoredResult(), m_expr1.get());
1014 return generator.emitNode(dst, m_expr2.get());
1015}
1016
1017// ------------------------------ ConstDeclNode ----------------------------------
1018
1019ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
1020 : ExpressionNode(globalData)
1021 , m_ident(ident)
1022 , m_init(init)
1023{
1024}
1025
1026RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
1027{
1028 if (RegisterID* local = generator.constRegisterFor(m_ident)) {
1029 if (!m_init)
1030 return local;
1031
1032 return generator.emitNode(local, m_init.get());
1033 }
1034
1035 // FIXME: While this code should only be hit in eval code, it will potentially
1036 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1037 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1038 RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined());
1039 return generator.emitPutById(base.get(), m_ident, value);
1040}
1041
1042RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*)
1043{
1044 RegisterID* result = 0;
1045 for (ConstDeclNode* n = this; n; n = n->m_next.get())
1046 result = n->emitCodeSingle(generator);
1047
1048 return result;
1049}
1050
1051// ------------------------------ ConstStatementNode -----------------------------
1052
1053RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1054{
1055 return generator.emitNode(m_next.get());
1056}
1057
1058// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
1059
1060static inline RegisterID* statementListEmitCode(StatementVector& statements, CodeGenerator& generator, RegisterID* dst = 0)
1061{
1062 StatementVector::iterator end = statements.end();
1063 for (StatementVector::iterator it = statements.begin(); it != end; ++it) {
1064 StatementNode* n = it->get();
1065 if (!n->isLoop())
1066 generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
1067 generator.emitNode(dst, n);
1068 }
1069 return 0;
1070}
1071
1072static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
1073{
1074 StatementVector::iterator it = statements.end();
1075 StatementVector::iterator begin = statements.begin();
1076 while (it != begin) {
1077 --it;
1078 stack.append((*it).get());
1079 }
1080}
1081
1082static inline Node* statementListInitializeVariableAccessStack(StatementVector& statements, DeclarationStacks::NodeStack& stack)
1083{
1084 if (statements.isEmpty())
1085 return 0;
1086
1087 StatementVector::iterator it = statements.end();
1088 StatementVector::iterator begin = statements.begin();
1089 StatementVector::iterator beginPlusOne = begin + 1;
1090
1091 while (it != beginPlusOne) {
1092 --it;
1093 stack.append((*it).get());
1094 }
1095
1096 return (*begin).get();
1097}
1098
1099// ------------------------------ BlockNode ------------------------------------
1100
1101BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
1102 : StatementNode(globalData)
1103{
1104 if (children)
1105 children->releaseContentsIntoVector(m_children);
1106}
1107
1108RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1109{
1110 return statementListEmitCode(m_children, generator, dst);
1111}
1112
1113// ------------------------------ EmptyStatementNode ---------------------------
1114
1115RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst)
1116{
1117 return dst;
1118}
1119
1120// ------------------------------ DebuggerStatementNode ---------------------------
1121
1122RegisterID* DebuggerStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1123{
1124 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1125 return dst;
1126}
1127
1128// ------------------------------ ExprStatementNode ----------------------------
1129
1130RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1131{
1132 ASSERT(m_expr);
1133 return generator.emitNode(dst, m_expr.get());
1134}
1135
1136// ------------------------------ VarStatementNode ----------------------------
1137
1138RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1139{
1140 ASSERT(m_expr);
1141 return generator.emitNode(m_expr.get());
1142}
1143
1144// ------------------------------ IfNode ---------------------------------------
1145
1146RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1147{
1148 RefPtr<LabelID> afterThen = generator.newLabel();
1149
1150 RegisterID* cond = generator.emitNode(m_condition.get());
1151 generator.emitJumpIfFalse(cond, afterThen.get());
1152
1153 if (!m_ifBlock->isBlock())
1154 generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
1155
1156 generator.emitNode(dst, m_ifBlock.get());
1157 generator.emitLabel(afterThen.get());
1158
1159 // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
1160 return 0;
1161}
1162
1163RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1164{
1165 RefPtr<LabelID> beforeElse = generator.newLabel();
1166 RefPtr<LabelID> afterElse = generator.newLabel();
1167
1168 RegisterID* cond = generator.emitNode(m_condition.get());
1169 generator.emitJumpIfFalse(cond, beforeElse.get());
1170
1171 if (!m_ifBlock->isBlock())
1172 generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
1173
1174 generator.emitNode(dst, m_ifBlock.get());
1175 generator.emitJump(afterElse.get());
1176
1177 generator.emitLabel(beforeElse.get());
1178 generator.emitNode(dst, m_elseBlock.get());
1179
1180 generator.emitLabel(afterElse.get());
1181
1182 // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
1183 return 0;
1184}
1185
1186// ------------------------------ DoWhileNode ----------------------------------
1187
1188RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1189{
1190 RefPtr<LabelID> topOfLoop = generator.newLabel();
1191 generator.emitLabel(topOfLoop.get());
1192
1193 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1194
1195 if (!m_statement->isBlock())
1196 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1197
1198 RefPtr<LabelID> continueTarget = generator.newLabel();
1199 RefPtr<LabelID> breakTarget = generator.newLabel();
1200
1201 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1202 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1203 generator.popJumpContext();
1204
1205 generator.emitLabel(continueTarget.get());
1206 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1207 RegisterID* cond = generator.emitNode(m_expr.get());
1208 generator.emitJumpIfTrue(cond, topOfLoop.get());
1209
1210 generator.emitLabel(breakTarget.get());
1211 return result.get();
1212}
1213
1214// ------------------------------ WhileNode ------------------------------------
1215
1216RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1217{
1218 RefPtr<LabelID> topOfLoop = generator.newLabel();
1219 RefPtr<LabelID> continueTarget = generator.newLabel();
1220 RefPtr<LabelID> breakTarget = generator.newLabel();
1221
1222 generator.emitJump(continueTarget.get());
1223 generator.emitLabel(topOfLoop.get());
1224
1225 if (!m_statement->isBlock())
1226 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1227
1228 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1229 generator.emitNode(dst, m_statement.get());
1230 generator.popJumpContext();
1231
1232 generator.emitLabel(continueTarget.get());
1233 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1234 RegisterID* cond = generator.emitNode(m_expr.get());
1235 generator.emitJumpIfTrue(cond, topOfLoop.get());
1236
1237 generator.emitLabel(breakTarget.get());
1238
1239 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1240 return 0;
1241}
1242
1243// ------------------------------ ForNode --------------------------------------
1244
1245RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1246{
1247 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1248
1249 if (m_expr1)
1250 generator.emitNode(ignoredResult(), m_expr1.get());
1251
1252 RefPtr<LabelID> topOfLoop = generator.newLabel();
1253 RefPtr<LabelID> beforeCondition = generator.newLabel();
1254 RefPtr<LabelID> continueTarget = generator.newLabel();
1255 RefPtr<LabelID> breakTarget = generator.newLabel();
1256 generator.emitJump(beforeCondition.get());
1257
1258 generator.emitLabel(topOfLoop.get());
1259 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1260 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1261 generator.popJumpContext();
1262 generator.emitLabel(continueTarget.get());
1263 if (m_expr3)
1264 generator.emitNode(ignoredResult(), m_expr3.get());
1265
1266 generator.emitLabel(beforeCondition.get());
1267 if (m_expr2) {
1268 RegisterID* cond = generator.emitNode(m_expr2.get());
1269 generator.emitJumpIfTrue(cond, topOfLoop.get());
1270 } else {
1271 generator.emitJump(topOfLoop.get());
1272 }
1273
1274 if (!m_statement->isBlock())
1275 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1276
1277 generator.emitLabel(breakTarget.get());
1278
1279 return result.get();
1280}
1281
1282// ------------------------------ ForInNode ------------------------------------
1283
1284ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
1285 : StatementNode(globalData)
1286 , m_init(0L)
1287 , m_lexpr(l)
1288 , m_expr(expr)
1289 , m_statement(statement)
1290 , m_identIsVarDecl(false)
1291{
1292}
1293
1294ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset)
1295 : StatementNode(globalData)
1296 , m_ident(ident)
1297 , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset))
1298 , m_expr(expr)
1299 , m_statement(statement)
1300 , m_identIsVarDecl(true)
1301{
1302 if (in) {
1303 AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true);
1304 node->setExceptionSourceRange(divot, divot - startOffset, endOffset - divot);
1305 m_init = node;
1306 }
1307 // for( var foo = bar in baz )
1308}
1309
1310RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1311{
1312 if (!m_lexpr->isLocation())
1313 return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
1314 RefPtr<LabelID> loopStart = generator.newLabel();
1315 RefPtr<LabelID> continueTarget = generator.newLabel();
1316 RefPtr<LabelID> breakTarget = generator.newLabel();
1317
1318 if (m_init)
1319 generator.emitNode(ignoredResult(), m_init.get());
1320 RegisterID* forInBase = generator.emitNode(m_expr.get());
1321 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
1322 generator.emitJump(continueTarget.get());
1323 generator.emitLabel(loopStart.get());
1324 RegisterID* propertyName;
1325 if (m_lexpr->isResolveNode()) {
1326 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
1327 propertyName = generator.registerFor(ident);
1328 if (!propertyName) {
1329 propertyName = generator.newTemporary();
1330 RefPtr<RegisterID> protect = propertyName;
1331 RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
1332
1333 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1334 generator.emitPutById(base, ident, propertyName);
1335 }
1336 } else if (m_lexpr->isDotAccessorNode()) {
1337 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
1338 const Identifier& ident = assignNode->identifier();
1339 propertyName = generator.newTemporary();
1340 RefPtr<RegisterID> protect = propertyName;
1341 RegisterID* base = generator.emitNode(assignNode->base());
1342
1343 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1344 generator.emitPutById(base, ident, propertyName);
1345 } else {
1346 ASSERT(m_lexpr->isBracketAccessorNode());
1347 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
1348 propertyName = generator.newTemporary();
1349 RefPtr<RegisterID> protect = propertyName;
1350 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1351 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1352
1353 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1354 generator.emitPutByVal(base.get(), subscript, propertyName);
1355 }
1356
1357 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1358 generator.emitNode(dst, m_statement.get());
1359 generator.popJumpContext();
1360
1361 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1362
1363 if (!m_statement->isBlock())
1364 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1365
1366 generator.emitLabel(continueTarget.get());
1367 generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
1368 generator.emitLabel(breakTarget.get());
1369 return dst;
1370}
1371
1372// ------------------------------ ContinueNode ---------------------------------
1373
1374// ECMA 12.7
1375RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1376{
1377 if (!generator.inContinueContext())
1378 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1379
1380 JumpContext* targetContext = generator.jumpContextForContinue(m_ident);
1381
1382 if (!targetContext) {
1383 if (m_ident.isEmpty())
1384 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1385 else
1386 return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
1387 }
1388
1389 if (!targetContext->continueTarget)
1390 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1391
1392 generator.emitJumpScopes(targetContext->continueTarget, targetContext->scopeDepth);
1393
1394 return dst;
1395}
1396
1397// ------------------------------ BreakNode ------------------------------------
1398
1399// ECMA 12.8
1400RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1401{
1402 if (!generator.inJumpContext())
1403 return emitThrowError(generator, SyntaxError, "Invalid break statement.");
1404
1405 JumpContext* targetContext = generator.jumpContextForBreak(m_ident);
1406
1407 if (!targetContext) {
1408 if (m_ident.isEmpty())
1409 return emitThrowError(generator, SyntaxError, "Invalid break statement.");
1410 else
1411 return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
1412 }
1413
1414 ASSERT(targetContext->breakTarget);
1415
1416 generator.emitJumpScopes(targetContext->breakTarget, targetContext->scopeDepth);
1417
1418 return dst;
1419}
1420
1421// ------------------------------ ReturnNode -----------------------------------
1422
1423RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1424{
1425 if (generator.codeType() != FunctionCode)
1426 return emitThrowError(generator, SyntaxError, "Invalid return statement.");
1427
1428 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined());
1429 if (generator.scopeDepth()) {
1430 RefPtr<LabelID> l0 = generator.newLabel();
1431 generator.emitJumpScopes(l0.get(), 0);
1432 generator.emitLabel(l0.get());
1433 }
1434 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1435 return generator.emitReturn(r0);
1436}
1437
1438// ------------------------------ WithNode -------------------------------------
1439
1440RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1441{
1442 RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped
1443 generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
1444 generator.emitPushScope(scope.get());
1445 RegisterID* result = generator.emitNode(dst, m_statement.get());
1446 generator.emitPopScope();
1447 return result;
1448}
1449
1450// ------------------------------ CaseBlockNode --------------------------------
1451enum SwitchKind {
1452 SwitchUnset = 0,
1453 SwitchNumber = 1,
1454 SwitchString = 2,
1455 SwitchNeither = 3
1456};
1457
1458static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
1459{
1460 for (; list; list = list->getNext()) {
1461 ExpressionNode* clauseExpression = list->getClause()->expr();
1462 literalVector.append(clauseExpression);
1463 if (clauseExpression->isNumber()) {
1464 double value = static_cast<NumberNode*>(clauseExpression)->value();
1465 if ((typeForTable & ~SwitchNumber) || !JSImmediate::from(value)) {
1466 typeForTable = SwitchNeither;
1467 break;
1468 }
1469 int32_t intVal = static_cast<int32_t>(value);
1470 ASSERT(intVal == value);
1471 if (intVal < min_num)
1472 min_num = intVal;
1473 if (intVal > max_num)
1474 max_num = intVal;
1475 typeForTable = SwitchNumber;
1476 continue;
1477 }
1478 if (clauseExpression->isString()) {
1479 if (typeForTable & ~SwitchString) {
1480 typeForTable = SwitchNeither;
1481 break;
1482 }
1483 const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
1484 if (singleCharacterSwitch &= value.size() == 1) {
1485 int32_t intVal = value.rep()->data()[0];
1486 if (intVal < min_num)
1487 min_num = intVal;
1488 if (intVal > max_num)
1489 max_num = intVal;
1490 }
1491 typeForTable = SwitchString;
1492 continue;
1493 }
1494 typeForTable = SwitchNeither;
1495 break;
1496 }
1497}
1498
1499SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
1500{
1501 SwitchKind typeForTable = SwitchUnset;
1502 bool singleCharacterSwitch = true;
1503
1504 processClauseList(m_list1.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1505 processClauseList(m_list2.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1506
1507 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
1508 return SwitchInfo::SwitchNone;
1509
1510 if (typeForTable == SwitchNumber) {
1511 int32_t range = max_num - min_num;
1512 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1513 return SwitchInfo::SwitchImmediate;
1514 return SwitchInfo::SwitchNone;
1515 }
1516
1517 ASSERT(typeForTable == SwitchString);
1518
1519 if (singleCharacterSwitch) {
1520 int32_t range = max_num - min_num;
1521 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1522 return SwitchInfo::SwitchCharacter;
1523 }
1524
1525 return SwitchInfo::SwitchString;
1526}
1527
1528RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
1529{
1530 RefPtr<LabelID> defaultLabel;
1531 Vector<RefPtr<LabelID>, 8> labelVector;
1532 Vector<ExpressionNode*, 8> literalVector;
1533 int32_t min_num = std::numeric_limits<int32_t>::max();
1534 int32_t max_num = std::numeric_limits<int32_t>::min();
1535 SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
1536
1537 if (switchType != SwitchInfo::SwitchNone) {
1538 // Prepare the various labels
1539 for (uint32_t i = 0; i < literalVector.size(); i++)
1540 labelVector.append(generator.newLabel());
1541 defaultLabel = generator.newLabel();
1542 generator.beginSwitch(switchExpression, switchType);
1543 } else {
1544 // Setup jumps
1545 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
1546 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1547 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1548 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
1549 labelVector.append(generator.newLabel());
1550 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1551 }
1552
1553 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
1554 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1555 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1556 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
1557 labelVector.append(generator.newLabel());
1558 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1559 }
1560 defaultLabel = generator.newLabel();
1561 generator.emitJump(defaultLabel.get());
1562 }
1563
1564 RegisterID* result = 0;
1565
1566 size_t i = 0;
1567 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
1568 generator.emitLabel(labelVector[i++].get());
1569 result = statementListEmitCode(list->getClause()->children(), generator, dst);
1570 }
1571
1572 if (m_defaultClause) {
1573 generator.emitLabel(defaultLabel.get());
1574 result = statementListEmitCode(m_defaultClause->children(), generator, dst);
1575 }
1576
1577 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
1578 generator.emitLabel(labelVector[i++].get());
1579 result = statementListEmitCode(list->getClause()->children(), generator, dst);
1580 }
1581 if (!m_defaultClause)
1582 generator.emitLabel(defaultLabel.get());
1583
1584 ASSERT(i == labelVector.size());
1585 if (switchType != SwitchInfo::SwitchNone) {
1586 ASSERT(labelVector.size() == literalVector.size());
1587 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
1588 }
1589 return result;
1590}
1591
1592// ------------------------------ SwitchNode -----------------------------------
1593
1594RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1595{
1596 RefPtr<LabelID> breakTarget = generator.newLabel();
1597
1598 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
1599 generator.pushJumpContext(&m_labelStack, 0, breakTarget.get(), true);
1600 RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst);
1601 generator.popJumpContext();
1602
1603 generator.emitLabel(breakTarget.get());
1604
1605 return r1;
1606}
1607
1608// ------------------------------ LabelNode ------------------------------------
1609
1610RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1611{
1612 if (generator.jumpContextForBreak(m_label))
1613 return emitThrowError(generator, SyntaxError, "Duplicated label %s found.", m_label);
1614
1615 RefPtr<LabelID> l0 = generator.newLabel();
1616 m_labelStack.push(m_label);
1617 generator.pushJumpContext(&m_labelStack, 0, l0.get(), false);
1618
1619 RegisterID* r0 = generator.emitNode(dst, m_statement.get());
1620
1621 generator.popJumpContext();
1622 m_labelStack.pop();
1623
1624 generator.emitLabel(l0.get());
1625 return r0;
1626}
1627
1628// ------------------------------ ThrowNode ------------------------------------
1629
1630RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1631{
1632 RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get());
1633 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1634 generator.emitThrow(expr.get());
1635 return dst;
1636}
1637
1638// ------------------------------ TryNode --------------------------------------
1639
1640RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1641{
1642 RefPtr<LabelID> tryStartLabel = generator.newLabel();
1643 RefPtr<LabelID> tryEndLabel = generator.newLabel();
1644 RefPtr<LabelID> finallyStart;
1645 RefPtr<RegisterID> finallyReturnAddr;
1646 if (m_finallyBlock) {
1647 finallyStart = generator.newLabel();
1648 finallyReturnAddr = generator.newTemporary();
1649 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
1650 }
1651 generator.emitLabel(tryStartLabel.get());
1652 generator.emitNode(dst, m_tryBlock.get());
1653 generator.emitLabel(tryEndLabel.get());
1654
1655 if (m_catchBlock) {
1656 RefPtr<LabelID> handlerEndLabel = generator.newLabel();
1657 generator.emitJump(handlerEndLabel.get());
1658 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
1659 generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
1660 generator.emitNode(dst, m_catchBlock.get());
1661 generator.emitPopScope();
1662 generator.emitLabel(handlerEndLabel.get());
1663 }
1664
1665 if (m_finallyBlock) {
1666 generator.popFinallyContext();
1667 // there may be important registers live at the time we jump
1668 // to a finally block (such as for a return or throw) so we
1669 // ref the highest register ever used as a conservative
1670 // approach to not clobbering anything important
1671 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
1672 RefPtr<LabelID> finallyEndLabel = generator.newLabel();
1673 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1674 // Use a label to record the subtle fact that sret will return to the
1675 // next instruction. sret is the only way to jump without an explicit label.
1676 generator.emitLabel(generator.newLabel().get());
1677 generator.emitJump(finallyEndLabel.get());
1678
1679 // Finally block for exception path
1680 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
1681 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1682 // Use a label to record the subtle fact that sret will return to the
1683 // next instruction. sret is the only way to jump without an explicit label.
1684 generator.emitLabel(generator.newLabel().get());
1685 generator.emitThrow(tempExceptionRegister.get());
1686
1687 // emit the finally block itself
1688 generator.emitLabel(finallyStart.get());
1689 generator.emitNode(dst, m_finallyBlock.get());
1690 generator.emitSubroutineReturn(finallyReturnAddr.get());
1691
1692 generator.emitLabel(finallyEndLabel.get());
1693 }
1694
1695 return dst;
1696}
1697
1698
1699// ------------------------------ ScopeNode -----------------------------
1700
1701ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
1702 : BlockNode(globalData, children)
1703 , m_source(source)
1704 , m_features(features)
1705 , m_numConstants(numConstants)
1706{
1707 if (varStack)
1708 m_varStack = *varStack;
1709 if (funcStack)
1710 m_functionStack = *funcStack;
1711
1712 SCOPENODE_SAMPLING_notifyOfScope(globalData->machine->m_sampler);
1713}
1714
1715// ------------------------------ ProgramNode -----------------------------
1716
1717ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1718 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
1719{
1720}
1721
1722ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1723{
1724 return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
1725}
1726
1727// ------------------------------ EvalNode -----------------------------
1728
1729EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1730 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
1731{
1732}
1733
1734RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*)
1735{
1736 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1737
1738 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1739 generator.emitLoad(dstRegister.get(), jsUndefined());
1740 statementListEmitCode(m_children, generator, dstRegister.get());
1741
1742 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1743 generator.emitEnd(dstRegister.get());
1744 return 0;
1745}
1746
1747void EvalNode::generateCode(ScopeChainNode* scopeChainNode)
1748{
1749 ScopeChain scopeChain(scopeChainNode);
1750 JSGlobalObject* globalObject = scopeChain.globalObject();
1751
1752 SymbolTable symbolTable;
1753 m_code.set(new EvalCodeBlock(this, globalObject, source().provider()));
1754
1755 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &symbolTable, m_code.get());
1756 generator.generate();
1757}
1758
1759EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1760{
1761 return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
1762}
1763
1764// ------------------------------ FunctionBodyNode -----------------------------
1765
1766FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
1767 : ScopeNode(globalData, SourceCode(), children, varStack, funcStack, features, numConstants)
1768 , m_parameters(0)
1769 , m_refCount(0)
1770{
1771}
1772
1773FunctionBodyNode::~FunctionBodyNode()
1774{
1775 if (m_parameters)
1776 fastFree(m_parameters);
1777}
1778
1779void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
1780{
1781 Vector<Identifier> parameters;
1782 for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
1783 parameters.append(parameter->ident());
1784 size_t count = parameters.size();
1785 finishParsing(source, parameters.releaseBuffer(), count);
1786}
1787
1788void FunctionBodyNode::finishParsing(const SourceCode& source, Identifier* parameters, size_t parameterCount)
1789{
1790 setSource(source);
1791 m_parameters = parameters;
1792 m_parameterCount = parameterCount;
1793}
1794
1795void FunctionBodyNode::mark()
1796{
1797 if (m_code)
1798 m_code->mark();
1799}
1800
1801FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
1802{
1803 return new FunctionBodyNode(globalData, children, varStack, funcStack, features, numConstants);
1804}
1805
1806FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode&, CodeFeatures features, int numConstants)
1807{
1808 return new FunctionBodyNode(globalData, children, varStack, funcStack, features, numConstants);
1809}
1810
1811void FunctionBodyNode::generateCode(ScopeChainNode* scopeChainNode)
1812{
1813 ScopeChain scopeChain(scopeChainNode);
1814 JSGlobalObject* globalObject = scopeChain.globalObject();
1815
1816 m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
1817
1818 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_symbolTable, m_code.get());
1819 generator.generate();
1820}
1821
1822RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*)
1823{
1824 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
1825 statementListEmitCode(m_children, generator);
1826 if (!m_children.size() || !m_children.last()->isReturnNode()) {
1827 RegisterID* r0 = generator.emitLoad(0, jsUndefined());
1828 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1829 generator.emitReturn(r0);
1830 }
1831 return 0;
1832}
1833
1834RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*)
1835{
1836 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1837
1838 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1839 generator.emitLoad(dstRegister.get(), jsUndefined());
1840 statementListEmitCode(m_children, generator, dstRegister.get());
1841
1842 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1843 generator.emitEnd(dstRegister.get());
1844 return 0;
1845}
1846
1847void ProgramNode::generateCode(ScopeChainNode* scopeChainNode)
1848{
1849 ScopeChain scopeChain(scopeChainNode);
1850 JSGlobalObject* globalObject = scopeChain.globalObject();
1851
1852 m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
1853
1854 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack);
1855 generator.generate();
1856}
1857
1858UString FunctionBodyNode::paramString() const
1859{
1860 UString s("");
1861 for (size_t pos = 0; pos < m_parameterCount; ++pos) {
1862 if (!s.isEmpty())
1863 s += ", ";
1864 s += parameters()[pos].ustring();
1865 }
1866
1867 return s;
1868}
1869
1870// ------------------------------ FuncDeclNode ---------------------------------
1871
1872JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
1873{
1874 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
1875
1876 JSObject* proto = constructEmptyObject(exec);
1877 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
1878 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
1879 return func;
1880}
1881
1882RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst)
1883{
1884 return dst;
1885}
1886
1887// ------------------------------ FuncExprNode ---------------------------------
1888
1889RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1890{
1891 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
1892}
1893
1894JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
1895{
1896 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
1897 JSObject* proto = constructEmptyObject(exec);
1898 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
1899 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
1900
1901 /*
1902 The Identifier in a FunctionExpression can be referenced from inside
1903 the FunctionExpression's FunctionBody to allow the function to call
1904 itself recursively. However, unlike in a FunctionDeclaration, the
1905 Identifier in a FunctionExpression cannot be referenced from and
1906 does not affect the scope enclosing the FunctionExpression.
1907 */
1908
1909 if (!m_ident.isNull()) {
1910 JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
1911 func->scope().push(functionScopeObject);
1912 }
1913
1914 return func;
1915}
1916
1917} // namespace JSC
Note: See TracBrowser for help on using the repository browser.