1 /* 2 * Copyright (C) 1999-2002 Harri Porten (porten (at) kde.org) 3 * Copyright (C) 2001 Peter Kelly (pmk (at) post.com) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich (at) uwaterloo.ca) 6 * Copyright (C) 2007 Maks Orlovich 7 * Copyright (C) 2007 Eric Seidel <eric (at) webkit.org> 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 #include "NodeConstructors.h" 29 30 #include "BytecodeGenerator.h" 31 #include "CallFrame.h" 32 #include "Debugger.h" 33 #include "JIT.h" 34 #include "JSFunction.h" 35 #include "JSGlobalObject.h" 36 #include "JSStaticScopeObject.h" 37 #include "LabelScope.h" 38 #include "Lexer.h" 39 #include "Operations.h" 40 #include "Parser.h" 41 #include "PropertyNameArray.h" 42 #include "RegExpCache.h" 43 #include "RegExpObject.h" 44 #include "SamplingTool.h" 45 #include "UStringConcatenate.h" 46 #include <wtf/Assertions.h> 47 #include <wtf/RefCountedLeakCounter.h> 48 #include <wtf/Threading.h> 49 50 using namespace WTF; 51 52 namespace JSC { 53 54 /* 55 Details of the emitBytecode function. 56 57 Return value: The register holding the production's value. 58 dst: An optional parameter specifying the most efficient destination at 59 which to store the production's value. The callee must honor dst. 60 61 The dst argument provides for a crude form of copy propagation. For example, 62 63 x = 1 64 65 becomes 66 67 load r[x], 1 68 69 instead of 70 71 load r0, 1 72 mov r[x], r0 73 74 because the assignment node, "x =", passes r[x] as dst to the number node, "1". 75 */ 76 77 // ------------------------------ ThrowableExpressionData -------------------------------- 78 79 RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const UString& message) 80 { 81 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 82 generator.emitThrowReferenceError(message); 83 return generator.newTemporary(); 84 } 85 86 // ------------------------------ NullNode ------------------------------------- 87 88 RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 89 { 90 if (dst == generator.ignoredResult()) 91 return 0; 92 return generator.emitLoad(dst, jsNull()); 93 } 94 95 // ------------------------------ BooleanNode ---------------------------------- 96 97 RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 98 { 99 if (dst == generator.ignoredResult()) 100 return 0; 101 return generator.emitLoad(dst, m_value); 102 } 103 104 // ------------------------------ NumberNode ----------------------------------- 105 106 RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 107 { 108 if (dst == generator.ignoredResult()) 109 return 0; 110 return generator.emitLoad(dst, m_value); 111 } 112 113 // ------------------------------ StringNode ----------------------------------- 114 115 RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 116 { 117 if (dst == generator.ignoredResult()) 118 return 0; 119 return generator.emitLoad(dst, m_value); 120 } 121 122 // ------------------------------ RegExpNode ----------------------------------- 123 124 RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 125 { 126 if (dst == generator.ignoredResult()) 127 return 0; 128 return generator.emitNewRegExp(generator.finalDestination(dst), 129 generator.globalData()->regExpCache()->lookupOrCreate(m_pattern.ustring(), regExpFlags(m_flags.ustring()))); 130 } 131 132 // ------------------------------ ThisNode ------------------------------------- 133 134 RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 135 { 136 if (dst == generator.ignoredResult()) 137 return 0; 138 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister()); 139 } 140 141 // ------------------------------ ResolveNode ---------------------------------- 142 143 bool ResolveNode::isPure(BytecodeGenerator& generator) const 144 { 145 return generator.isLocal(m_ident); 146 } 147 148 RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 149 { 150 if (RegisterID* local = generator.registerFor(m_ident)) { 151 if (dst == generator.ignoredResult()) 152 return 0; 153 return generator.moveToDestinationIfNeeded(dst, local); 154 } 155 156 generator.emitExpressionInfo(m_startOffset + m_ident.length(), m_ident.length(), 0); 157 return generator.emitResolve(generator.finalDestination(dst), m_ident); 158 } 159 160 // ------------------------------ ArrayNode ------------------------------------ 161 162 RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 163 { 164 // FIXME: Should we put all of this code into emitNewArray? 165 166 unsigned length = 0; 167 ElementNode* firstPutElement; 168 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) { 169 if (firstPutElement->elision()) 170 break; 171 ++length; 172 } 173 174 if (!firstPutElement && !m_elision) 175 return generator.emitNewArray(generator.finalDestination(dst), m_element); 176 177 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element); 178 179 for (ElementNode* n = firstPutElement; n; n = n->next()) { 180 RegisterID* value = generator.emitNode(n->value()); 181 length += n->elision(); 182 generator.emitPutByIndex(array.get(), length++, value); 183 } 184 185 if (m_elision) { 186 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length)); 187 generator.emitPutById(array.get(), generator.propertyNames().length, value); 188 } 189 190 return generator.moveToDestinationIfNeeded(dst, array.get()); 191 } 192 193 bool ArrayNode::isSimpleArray() const 194 { 195 if (m_elision || m_optional) 196 return false; 197 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) { 198 if (ptr->elision()) 199 return false; 200 } 201 return true; 202 } 203 204 ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const 205 { 206 ASSERT(!m_elision && !m_optional); 207 ElementNode* ptr = m_element; 208 if (!ptr) 209 return 0; 210 ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value()); 211 ArgumentListNode* tail = head; 212 ptr = ptr->next(); 213 for (; ptr; ptr = ptr->next()) { 214 ASSERT(!ptr->elision()); 215 tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value()); 216 } 217 return head; 218 } 219 220 // ------------------------------ ObjectLiteralNode ---------------------------- 221 222 RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 223 { 224 if (!m_list) { 225 if (dst == generator.ignoredResult()) 226 return 0; 227 return generator.emitNewObject(generator.finalDestination(dst)); 228 } 229 return generator.emitNode(dst, m_list); 230 } 231 232 // ------------------------------ PropertyListNode ----------------------------- 233 234 RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 235 { 236 RefPtr<RegisterID> newObj = generator.tempDestination(dst); 237 238 generator.emitNewObject(newObj.get()); 239 240 for (PropertyListNode* p = this; p; p = p->m_next) { 241 RegisterID* value = generator.emitNode(p->m_node->m_assign); 242 243 switch (p->m_node->m_type) { 244 case PropertyNode::Constant: { 245 generator.emitDirectPutById(newObj.get(), p->m_node->name(), value); 246 break; 247 } 248 case PropertyNode::Getter: { 249 generator.emitPutGetter(newObj.get(), p->m_node->name(), value); 250 break; 251 } 252 case PropertyNode::Setter: { 253 generator.emitPutSetter(newObj.get(), p->m_node->name(), value); 254 break; 255 } 256 default: 257 ASSERT_NOT_REACHED(); 258 } 259 } 260 261 return generator.moveToDestinationIfNeeded(dst, newObj.get()); 262 } 263 264 // ------------------------------ BracketAccessorNode -------------------------------- 265 266 RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 267 { 268 if (m_base->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())) { 269 RegisterID* property = generator.emitNode(m_subscript); 270 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 271 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property); 272 } 273 274 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator)); 275 RegisterID* property = generator.emitNode(m_subscript); 276 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 277 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property); 278 } 279 280 // ------------------------------ DotAccessorNode -------------------------------- 281 282 RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 283 { 284 if (m_ident == generator.propertyNames().length) { 285 if (!m_base->isResolveNode()) 286 goto nonArgumentsPath; 287 ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base); 288 if (!generator.willResolveToArguments(resolveNode->identifier())) 289 goto nonArgumentsPath; 290 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 291 return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments()); 292 } 293 294 nonArgumentsPath: 295 RegisterID* base = generator.emitNode(m_base); 296 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 297 return generator.emitGetById(generator.finalDestination(dst), base, m_ident); 298 } 299 300 // ------------------------------ ArgumentListNode ----------------------------- 301 302 RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 303 { 304 ASSERT(m_expr); 305 return generator.emitNode(dst, m_expr); 306 } 307 308 // ------------------------------ NewExprNode ---------------------------------- 309 310 RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 311 { 312 RefPtr<RegisterID> func = generator.emitNode(m_expr); 313 CallArguments callArguments(generator, m_args); 314 return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), callArguments, divot(), startOffset(), endOffset()); 315 } 316 317 CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode) 318 : m_argumentsNode(argumentsNode) 319 { 320 if (generator.shouldEmitProfileHooks()) 321 m_profileHookRegister = generator.newTemporary(); 322 m_argv.append(generator.newTemporary()); 323 if (argumentsNode) { 324 for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) { 325 m_argv.append(generator.newTemporary()); 326 // op_call requires the arguments to be a sequential range of registers 327 ASSERT(m_argv[m_argv.size() - 1]->index() == m_argv[m_argv.size() - 2]->index() + 1); 328 } 329 } 330 } 331 332 // ------------------------------ EvalFunctionCallNode ---------------------------------- 333 334 RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 335 { 336 RefPtr<RegisterID> func = generator.tempDestination(dst); 337 CallArguments callArguments(generator, m_args); 338 generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0); 339 generator.emitResolveWithBase(callArguments.thisRegister(), func.get(), generator.propertyNames().eval); 340 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); 341 } 342 343 // ------------------------------ FunctionCallValueNode ---------------------------------- 344 345 RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 346 { 347 RefPtr<RegisterID> func = generator.emitNode(m_expr); 348 CallArguments callArguments(generator, m_args); 349 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 350 return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); 351 } 352 353 // ------------------------------ FunctionCallResolveNode ---------------------------------- 354 355 RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 356 { 357 if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { 358 CallArguments callArguments(generator, m_args); 359 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 360 return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), local.get(), callArguments, divot(), startOffset(), endOffset()); 361 } 362 363 int index = 0; 364 size_t depth = 0; 365 JSObject* globalObject = 0; 366 bool requiresDynamicChecks = false; 367 if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { 368 RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); 369 CallArguments callArguments(generator, m_args); 370 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 371 return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); 372 } 373 374 RefPtr<RegisterID> func = generator.newTemporary(); 375 CallArguments callArguments(generator, m_args); 376 int identifierStart = divot() - startOffset(); 377 generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0); 378 generator.emitResolveWithBase(callArguments.thisRegister(), func.get(), m_ident); 379 return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); 380 } 381 382 // ------------------------------ FunctionCallBracketNode ---------------------------------- 383 384 RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 385 { 386 RefPtr<RegisterID> base = generator.emitNode(m_base); 387 RegisterID* property = generator.emitNode(m_subscript); 388 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 389 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); 390 CallArguments callArguments(generator, m_args); 391 generator.emitMove(callArguments.thisRegister(), base.get()); 392 return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset()); 393 } 394 395 // ------------------------------ FunctionCallDotNode ---------------------------------- 396 397 RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 398 { 399 RefPtr<RegisterID> function = generator.tempDestination(dst); 400 CallArguments callArguments(generator, m_args); 401 generator.emitNode(callArguments.thisRegister(), m_base); 402 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 403 generator.emitMethodCheck(); 404 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident); 405 return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset()); 406 } 407 408 RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 409 { 410 RefPtr<Label> realCall = generator.newLabel(); 411 RefPtr<Label> end = generator.newLabel(); 412 RefPtr<RegisterID> base = generator.emitNode(m_base); 413 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 414 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); 415 RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get()); 416 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get()); 417 { 418 if (m_args->m_listNode && m_args->m_listNode->m_expr) { 419 ArgumentListNode* oldList = m_args->m_listNode; 420 m_args->m_listNode = m_args->m_listNode->m_next; 421 422 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 423 CallArguments callArguments(generator, m_args); 424 generator.emitNode(callArguments.thisRegister(), oldList->m_expr); 425 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); 426 generator.emitJump(end.get()); 427 428 m_args->m_listNode = oldList; 429 430 } else { 431 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 432 CallArguments callArguments(generator, m_args); 433 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 434 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); 435 generator.emitJump(end.get()); 436 } 437 } 438 generator.emitLabel(realCall.get()); 439 { 440 CallArguments callArguments(generator, m_args); 441 generator.emitMove(callArguments.thisRegister(), base.get()); 442 generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset()); 443 } 444 generator.emitLabel(end.get()); 445 return finalDestinationOrIgnored.get(); 446 } 447 448 static bool areTrivialApplyArguments(ArgumentsNode* args) 449 { 450 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next 451 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray()); 452 } 453 454 RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 455 { 456 // A few simple cases can be trivially handled as ordinary function calls. 457 // function.apply(), function.apply(arg) -> identical to function.call 458 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation 459 bool mayBeCall = areTrivialApplyArguments(m_args); 460 461 RefPtr<Label> realCall = generator.newLabel(); 462 RefPtr<Label> end = generator.newLabel(); 463 RefPtr<RegisterID> base = generator.emitNode(m_base); 464 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 465 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); 466 RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get()); 467 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get()); 468 { 469 if (mayBeCall) { 470 if (m_args->m_listNode && m_args->m_listNode->m_expr) { 471 ArgumentListNode* oldList = m_args->m_listNode; 472 if (m_args->m_listNode->m_next) { 473 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray()); 474 ASSERT(!m_args->m_listNode->m_next->m_next); 475 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.globalData()); 476 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 477 CallArguments callArguments(generator, m_args); 478 generator.emitNode(callArguments.thisRegister(), oldList->m_expr); 479 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); 480 } else { 481 m_args->m_listNode = m_args->m_listNode->m_next; 482 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 483 CallArguments callArguments(generator, m_args); 484 generator.emitNode(callArguments.thisRegister(), oldList->m_expr); 485 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); 486 } 487 m_args->m_listNode = oldList; 488 } else { 489 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 490 CallArguments callArguments(generator, m_args); 491 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 492 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); 493 } 494 } else { 495 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next); 496 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get()); 497 RefPtr<RegisterID> argsCountRegister = generator.newTemporary(); 498 RefPtr<RegisterID> thisRegister = generator.newTemporary(); 499 RefPtr<RegisterID> argsRegister = generator.newTemporary(); 500 generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); 501 ArgumentListNode* args = m_args->m_listNode->m_next; 502 bool isArgumentsApply = false; 503 if (args->m_expr->isResolveNode()) { 504 ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr); 505 isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier()); 506 if (isArgumentsApply) 507 generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments()); 508 } 509 if (!isArgumentsApply) 510 generator.emitNode(argsRegister.get(), args->m_expr); 511 while ((args = args->m_next)) 512 generator.emitNode(args->m_expr); 513 514 generator.emitLoadVarargs(argsCountRegister.get(), thisRegister.get(), argsRegister.get()); 515 generator.emitCallVarargs(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset()); 516 } 517 generator.emitJump(end.get()); 518 } 519 generator.emitLabel(realCall.get()); 520 { 521 CallArguments callArguments(generator, m_args); 522 generator.emitMove(callArguments.thisRegister(), base.get()); 523 generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset()); 524 } 525 generator.emitLabel(end.get()); 526 return finalDestinationOrIgnored.get(); 527 } 528 529 // ------------------------------ PostfixResolveNode ---------------------------------- 530 531 static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper) 532 { 533 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst); 534 } 535 536 static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper) 537 { 538 if (srcDst == dst) 539 return generator.emitToJSNumber(dst, srcDst); 540 return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst); 541 } 542 543 RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 544 { 545 if (RegisterID* local = generator.registerFor(m_ident)) { 546 if (generator.isLocalConstant(m_ident)) { 547 if (dst == generator.ignoredResult()) 548 return 0; 549 return generator.emitToJSNumber(generator.finalDestination(dst), local); 550 } 551 552 if (dst == generator.ignoredResult()) 553 return emitPreIncOrDec(generator, local, m_operator); 554 return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator); 555 } 556 557 int index = 0; 558 size_t depth = 0; 559 JSObject* globalObject = 0; 560 bool requiresDynamicChecks = false; 561 if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { 562 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); 563 RegisterID* oldValue; 564 if (dst == generator.ignoredResult()) { 565 oldValue = 0; 566 emitPreIncOrDec(generator, value.get(), m_operator); 567 } else { 568 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); 569 } 570 generator.emitPutScopedVar(depth, index, value.get(), globalObject); 571 return oldValue; 572 } 573 574 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 575 RefPtr<RegisterID> value = generator.newTemporary(); 576 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident); 577 RegisterID* oldValue; 578 if (dst == generator.ignoredResult()) { 579 oldValue = 0; 580 emitPreIncOrDec(generator, value.get(), m_operator); 581 } else { 582 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); 583 } 584 generator.emitPutById(base.get(), m_ident, value.get()); 585 return oldValue; 586 } 587 588 // ------------------------------ PostfixBracketNode ---------------------------------- 589 590 RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 591 { 592 RefPtr<RegisterID> base = generator.emitNode(m_base); 593 RefPtr<RegisterID> property = generator.emitNode(m_subscript); 594 595 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 596 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get()); 597 RegisterID* oldValue; 598 if (dst == generator.ignoredResult()) { 599 oldValue = 0; 600 if (m_operator == OpPlusPlus) 601 generator.emitPreInc(value.get()); 602 else 603 generator.emitPreDec(value.get()); 604 } else { 605 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); 606 } 607 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 608 generator.emitPutByVal(base.get(), property.get(), value.get()); 609 return oldValue; 610 } 611 612 // ------------------------------ PostfixDotNode ---------------------------------- 613 614 RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 615 { 616 RefPtr<RegisterID> base = generator.emitNode(m_base); 617 618 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 619 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident); 620 RegisterID* oldValue; 621 if (dst == generator.ignoredResult()) { 622 oldValue = 0; 623 if (m_operator == OpPlusPlus) 624 generator.emitPreInc(value.get()); 625 else 626 generator.emitPreDec(value.get()); 627 } else { 628 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); 629 } 630 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 631 generator.emitPutById(base.get(), m_ident, value.get()); 632 return oldValue; 633 } 634 635 // ------------------------------ PostfixErrorNode ----------------------------------- 636 637 RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 638 { 639 return emitThrowReferenceError(generator, m_operator == OpPlusPlus 640 ? "Postfix ++ operator applied to value that is not a reference." 641 : "Postfix -- operator applied to value that is not a reference."); 642 } 643 644 // ------------------------------ DeleteResolveNode ----------------------------------- 645 646 RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 647 { 648 if (generator.registerFor(m_ident)) 649 return generator.emitLoad(generator.finalDestination(dst), false); 650 651 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 652 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident); 653 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident); 654 } 655 656 // ------------------------------ DeleteBracketNode ----------------------------------- 657 658 RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 659 { 660 RefPtr<RegisterID> r0 = generator.emitNode(m_base); 661 RegisterID* r1 = generator.emitNode(m_subscript); 662 663 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 664 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1); 665 } 666 667 // ------------------------------ DeleteDotNode ----------------------------------- 668 669 RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 670 { 671 RegisterID* r0 = generator.emitNode(m_base); 672 673 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 674 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident); 675 } 676 677 // ------------------------------ DeleteValueNode ----------------------------------- 678 679 RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 680 { 681 generator.emitNode(generator.ignoredResult(), m_expr); 682 683 // delete on a non-location expression ignores the value and returns true 684 return generator.emitLoad(generator.finalDestination(dst), true); 685 } 686 687 // ------------------------------ VoidNode ------------------------------------- 688 689 RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 690 { 691 if (dst == generator.ignoredResult()) { 692 generator.emitNode(generator.ignoredResult(), m_expr); 693 return 0; 694 } 695 RefPtr<RegisterID> r0 = generator.emitNode(m_expr); 696 return generator.emitLoad(dst, jsUndefined()); 697 } 698 699 // ------------------------------ TypeOfValueNode ----------------------------------- 700 701 RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 702 { 703 if (RegisterID* local = generator.registerFor(m_ident)) { 704 if (dst == generator.ignoredResult()) 705 return 0; 706 return generator.emitTypeOf(generator.finalDestination(dst), local); 707 } 708 709 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident); 710 generator.emitGetById(scratch.get(), scratch.get(), m_ident); 711 if (dst == generator.ignoredResult()) 712 return 0; 713 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get()); 714 } 715 716 // ------------------------------ TypeOfValueNode ----------------------------------- 717 718 RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 719 { 720 if (dst == generator.ignoredResult()) { 721 generator.emitNode(generator.ignoredResult(), m_expr); 722 return 0; 723 } 724 RefPtr<RegisterID> src = generator.emitNode(m_expr); 725 return generator.emitTypeOf(generator.finalDestination(dst), src.get()); 726 } 727 728 // ------------------------------ PrefixResolveNode ---------------------------------- 729 730 RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 731 { 732 if (RegisterID* local = generator.registerFor(m_ident)) { 733 if (generator.isLocalConstant(m_ident)) { 734 if (dst == generator.ignoredResult()) 735 return 0; 736 RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0); 737 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes()); 738 } 739 740 emitPreIncOrDec(generator, local, m_operator); 741 return generator.moveToDestinationIfNeeded(dst, local); 742 } 743 744 int index = 0; 745 size_t depth = 0; 746 JSObject* globalObject = 0; 747 bool requiresDynamicChecks = false; 748 if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { 749 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); 750 emitPreIncOrDec(generator, propDst.get(), m_operator); 751 generator.emitPutScopedVar(depth, index, propDst.get(), globalObject); 752 return generator.moveToDestinationIfNeeded(dst, propDst.get()); 753 } 754 755 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 756 RefPtr<RegisterID> propDst = generator.tempDestination(dst); 757 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident); 758 emitPreIncOrDec(generator, propDst.get(), m_operator); 759 generator.emitPutById(base.get(), m_ident, propDst.get()); 760 return generator.moveToDestinationIfNeeded(dst, propDst.get()); 761 } 762 763 // ------------------------------ PrefixBracketNode ---------------------------------- 764 765 RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 766 { 767 RefPtr<RegisterID> base = generator.emitNode(m_base); 768 RefPtr<RegisterID> property = generator.emitNode(m_subscript); 769 RefPtr<RegisterID> propDst = generator.tempDestination(dst); 770 771 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); 772 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get()); 773 if (m_operator == OpPlusPlus) 774 generator.emitPreInc(value); 775 else 776 generator.emitPreDec(value); 777 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 778 generator.emitPutByVal(base.get(), property.get(), value); 779 return generator.moveToDestinationIfNeeded(dst, propDst.get()); 780 } 781 782 // ------------------------------ PrefixDotNode ---------------------------------- 783 784 RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 785 { 786 RefPtr<RegisterID> base = generator.emitNode(m_base); 787 RefPtr<RegisterID> propDst = generator.tempDestination(dst); 788 789 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); 790 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident); 791 if (m_operator == OpPlusPlus) 792 generator.emitPreInc(value); 793 else 794 generator.emitPreDec(value); 795 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 796 generator.emitPutById(base.get(), m_ident, value); 797 return generator.moveToDestinationIfNeeded(dst, propDst.get()); 798 } 799 800 // ------------------------------ PrefixErrorNode ----------------------------------- 801 802 RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 803 { 804 return emitThrowReferenceError(generator, m_operator == OpPlusPlus 805 ? "Prefix ++ operator applied to value that is not a reference." 806 : "Prefix -- operator applied to value that is not a reference."); 807 } 808 809 // ------------------------------ Unary Operation Nodes ----------------------------------- 810 811 RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 812 { 813 RegisterID* src = generator.emitNode(m_expr); 814 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src); 815 } 816 817 818 // ------------------------------ LogicalNotNode ----------------------------------- 819 820 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue) 821 { 822 ASSERT(expr()->hasConditionContextCodegen()); 823 824 // reverse the true and false targets 825 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, !fallThroughMeansTrue); 826 } 827 828 829 // ------------------------------ Binary Operation Nodes ----------------------------------- 830 831 // BinaryOpNode::emitStrcat: 832 // 833 // This node generates an op_strcat operation. This opcode can handle concatenation of three or 834 // more values, where we can determine a set of separate op_add operations would be operating on 835 // string values. 836 // 837 // This function expects to be operating on a graph of AST nodes looking something like this: 838 // 839 // (a)... (b) 840 // \ / 841 // (+) (c) 842 // \ / 843 // [d] ((+)) 844 // \ / 845 // [+=] 846 // 847 // The assignment operation is optional, if it exists the register holding the value on the 848 // lefthand side of the assignment should be passing as the optional 'lhs' argument. 849 // 850 // The method should be called on the node at the root of the tree of regular binary add 851 // operations (marked in the diagram with a double set of parentheses). This node must 852 // be performing a string concatenation (determined by statically detecting that at least 853 // one child must be a string). 854 // 855 // Since the minimum number of values being concatenated together is expected to be 3, if 856 // a lhs to a concatenating assignment is not provided then the root add should have at 857 // least one left child that is also an add that can be determined to be operating on strings. 858 // 859 RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe) 860 { 861 ASSERT(isAdd()); 862 ASSERT(resultDescriptor().definitelyIsString()); 863 864 // Create a list of expressions for all the adds in the tree of nodes we can convert into 865 // a string concatenation. The rightmost node (c) is added first. The rightmost node is 866 // added first, and the leftmost child is never added, so the vector produced for the 867 // example above will be [ c, b ]. 868 Vector<ExpressionNode*, 16> reverseExpressionList; 869 reverseExpressionList.append(m_expr2); 870 871 // Examine the left child of the add. So long as this is a string add, add its right-child 872 // to the list, and keep processing along the left fork. 873 ExpressionNode* leftMostAddChild = m_expr1; 874 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) { 875 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2); 876 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1; 877 } 878 879 Vector<RefPtr<RegisterID>, 16> temporaryRegisters; 880 881 // If there is an assignment, allocate a temporary to hold the lhs after conversion. 882 // We could possibly avoid this (the lhs is converted last anyway, we could let the 883 // op_strcat node handle its conversion if required). 884 if (lhs) 885 temporaryRegisters.append(generator.newTemporary()); 886 887 // Emit code for the leftmost node ((a) in the example). 888 temporaryRegisters.append(generator.newTemporary()); 889 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get(); 890 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild); 891 892 // Note on ordering of conversions: 893 // 894 // We maintain the same ordering of conversions as we would see if the concatenations 895 // was performed as a sequence of adds (otherwise this optimization could change 896 // behaviour should an object have been provided a valueOf or toString method). 897 // 898 // Considering the above example, the sequnce of execution is: 899 // * evaluate operand (a) 900 // * evaluate operand (b) 901 // * convert (a) to primitive <- (this would be triggered by the first add) 902 // * convert (b) to primitive <- (ditto) 903 // * evaluate operand (c) 904 // * convert (c) to primitive <- (this would be triggered by the second add) 905 // And optionally, if there is an assignment: 906 // * convert (d) to primitive <- (this would be triggered by the assigning addition) 907 // 908 // As such we do not plant an op to convert the leftmost child now. Instead, use 909 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion 910 // once the second node has been generated. However, if the leftmost child is an 911 // immediate we can trivially determine that no conversion will be required. 912 // If this is the case 913 if (leftMostAddChild->isString()) 914 leftMostAddChildTempRegister = 0; 915 916 while (reverseExpressionList.size()) { 917 ExpressionNode* node = reverseExpressionList.last(); 918 reverseExpressionList.removeLast(); 919 920 // Emit the code for the current node. 921 temporaryRegisters.append(generator.newTemporary()); 922 generator.emitNode(temporaryRegisters.last().get(), node); 923 924 // On the first iteration of this loop, when we first reach this point we have just 925 // generated the second node, which means it is time to convert the leftmost operand. 926 if (leftMostAddChildTempRegister) { 927 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister); 928 leftMostAddChildTempRegister = 0; // Only do this once. 929 } 930 // Plant a conversion for this node, if necessary. 931 if (!node->isString()) 932 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get()); 933 } 934 ASSERT(temporaryRegisters.size() >= 3); 935 936 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. 937 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. 938 if (emitExpressionInfoForMe) 939 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset()); 940 941 // If there is an assignment convert the lhs now. This will also copy lhs to 942 // the temporary register we allocated for it. 943 if (lhs) 944 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs); 945 946 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size()); 947 } 948 949 RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 950 { 951 OpcodeID opcodeID = this->opcodeID(); 952 953 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) 954 return emitStrcat(generator, dst); 955 956 if (opcodeID == op_neq) { 957 if (m_expr1->isNull() || m_expr2->isNull()) { 958 RefPtr<RegisterID> src = generator.tempDestination(dst); 959 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); 960 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get()); 961 } 962 } 963 964 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); 965 RegisterID* src2 = generator.emitNode(m_expr2); 966 return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); 967 } 968 969 RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 970 { 971 if (m_expr1->isNull() || m_expr2->isNull()) { 972 RefPtr<RegisterID> src = generator.tempDestination(dst); 973 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); 974 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get()); 975 } 976 977 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); 978 RegisterID* src2 = generator.emitNode(m_expr2); 979 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2); 980 } 981 982 RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 983 { 984 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); 985 RegisterID* src2 = generator.emitNode(m_expr2); 986 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2); 987 } 988 989 RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 990 { 991 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); 992 RegisterID* src2 = generator.emitNode(m_expr2); 993 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor())); 994 } 995 996 RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 997 { 998 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); 999 RegisterID* src2 = generator.emitNode(m_expr2); 1000 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1001 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); 1002 } 1003 1004 RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1005 { 1006 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); 1007 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2); 1008 1009 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1010 generator.emitCheckHasInstance(src2.get()); 1011 1012 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1013 RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype); 1014 1015 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1016 return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype); 1017 } 1018 1019 // ------------------------------ LogicalOpNode ---------------------------- 1020 1021 RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1022 { 1023 RefPtr<RegisterID> temp = generator.tempDestination(dst); 1024 RefPtr<Label> target = generator.newLabel(); 1025 1026 generator.emitNode(temp.get(), m_expr1); 1027 if (m_operator == OpLogicalAnd) 1028 generator.emitJumpIfFalse(temp.get(), target.get()); 1029 else 1030 generator.emitJumpIfTrue(temp.get(), target.get()); 1031 generator.emitNode(temp.get(), m_expr2); 1032 generator.emitLabel(target.get()); 1033 1034 return generator.moveToDestinationIfNeeded(dst, temp.get()); 1035 } 1036 1037 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue) 1038 { 1039 if (m_expr1->hasConditionContextCodegen()) { 1040 RefPtr<Label> afterExpr1 = generator.newLabel(); 1041 if (m_operator == OpLogicalAnd) 1042 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, true); 1043 else 1044 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), false); 1045 generator.emitLabel(afterExpr1.get()); 1046 } else { 1047 RegisterID* temp = generator.emitNode(m_expr1); 1048 if (m_operator == OpLogicalAnd) 1049 generator.emitJumpIfFalse(temp, falseTarget); 1050 else 1051 generator.emitJumpIfTrue(temp, trueTarget); 1052 } 1053 1054 if (m_expr2->hasConditionContextCodegen()) 1055 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMeansTrue); 1056 else { 1057 RegisterID* temp = generator.emitNode(m_expr2); 1058 if (fallThroughMeansTrue) 1059 generator.emitJumpIfFalse(temp, falseTarget); 1060 else 1061 generator.emitJumpIfTrue(temp, trueTarget); 1062 } 1063 } 1064 1065 // ------------------------------ ConditionalNode ------------------------------ 1066 1067 RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1068 { 1069 RefPtr<RegisterID> newDst = generator.finalDestination(dst); 1070 RefPtr<Label> beforeElse = generator.newLabel(); 1071 RefPtr<Label> afterElse = generator.newLabel(); 1072 1073 if (m_logical->hasConditionContextCodegen()) { 1074 RefPtr<Label> beforeThen = generator.newLabel(); 1075 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), true); 1076 generator.emitLabel(beforeThen.get()); 1077 } else { 1078 RegisterID* cond = generator.emitNode(m_logical); 1079 generator.emitJumpIfFalse(cond, beforeElse.get()); 1080 } 1081 1082 generator.emitNode(newDst.get(), m_expr1); 1083 generator.emitJump(afterElse.get()); 1084 1085 generator.emitLabel(beforeElse.get()); 1086 generator.emitNode(newDst.get(), m_expr2); 1087 1088 generator.emitLabel(afterElse.get()); 1089 1090 return newDst.get(); 1091 } 1092 1093 // ------------------------------ ReadModifyResolveNode ----------------------------------- 1094 1095 // FIXME: should this be moved to be a method on BytecodeGenerator? 1096 static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0) 1097 { 1098 OpcodeID opcodeID; 1099 switch (oper) { 1100 case OpMultEq: 1101 opcodeID = op_mul; 1102 break; 1103 case OpDivEq: 1104 opcodeID = op_div; 1105 break; 1106 case OpPlusEq: 1107 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString()) 1108 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe); 1109 opcodeID = op_add; 1110 break; 1111 case OpMinusEq: 1112 opcodeID = op_sub; 1113 break; 1114 case OpLShift: 1115 opcodeID = op_lshift; 1116 break; 1117 case OpRShift: 1118 opcodeID = op_rshift; 1119 break; 1120 case OpURShift: 1121 opcodeID = op_urshift; 1122 break; 1123 case OpAndEq: 1124 opcodeID = op_bitand; 1125 break; 1126 case OpXOrEq: 1127 opcodeID = op_bitxor; 1128 break; 1129 case OpOrEq: 1130 opcodeID = op_bitor; 1131 break; 1132 case OpModEq: 1133 opcodeID = op_mod; 1134 break; 1135 default: 1136 ASSERT_NOT_REACHED(); 1137 return dst; 1138 } 1139 1140 RegisterID* src2 = generator.emitNode(m_right); 1141 1142 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. 1143 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. 1144 if (emitExpressionInfoForMe) 1145 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset()); 1146 1147 return generator.emitBinaryOp(opcodeID, dst, src1, src2, types); 1148 } 1149 1150 RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1151 { 1152 if (RegisterID* local = generator.registerFor(m_ident)) { 1153 if (generator.isLocalConstant(m_ident)) { 1154 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1155 } 1156 1157 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { 1158 RefPtr<RegisterID> result = generator.newTemporary(); 1159 generator.emitMove(result.get(), local); 1160 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1161 generator.emitMove(local, result.get()); 1162 return generator.moveToDestinationIfNeeded(dst, result.get()); 1163 } 1164 1165 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1166 return generator.moveToDestinationIfNeeded(dst, result); 1167 } 1168 1169 int index = 0; 1170 size_t depth = 0; 1171 JSObject* globalObject = 0; 1172 bool requiresDynamicChecks = false; 1173 if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { 1174 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); 1175 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1176 generator.emitPutScopedVar(depth, index, result, globalObject); 1177 return result; 1178 } 1179 1180 RefPtr<RegisterID> src1 = generator.tempDestination(dst); 1181 generator.emitExpressionInfo(divot() - startOffset() + m_ident.length(), m_ident.length(), 0); 1182 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident); 1183 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); 1184 return generator.emitPutById(base.get(), m_ident, result); 1185 } 1186 1187 // ------------------------------ AssignResolveNode ----------------------------------- 1188 1189 RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1190 { 1191 if (RegisterID* local = generator.registerFor(m_ident)) { 1192 if (generator.isLocalConstant(m_ident)) 1193 return generator.emitNode(dst, m_right); 1194 1195 RegisterID* result = generator.emitNode(local, m_right); 1196 return generator.moveToDestinationIfNeeded(dst, result); 1197 } 1198 1199 int index = 0; 1200 size_t depth = 0; 1201 JSObject* globalObject = 0; 1202 bool requiresDynamicChecks = false; 1203 if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { 1204 if (dst == generator.ignoredResult()) 1205 dst = 0; 1206 RegisterID* value = generator.emitNode(dst, m_right); 1207 generator.emitPutScopedVar(depth, index, value, globalObject); 1208 return value; 1209 } 1210 1211 RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), m_ident); 1212 if (dst == generator.ignoredResult()) 1213 dst = 0; 1214 RegisterID* value = generator.emitNode(dst, m_right); 1215 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1216 return generator.emitPutById(base.get(), m_ident, value); 1217 } 1218 1219 // ------------------------------ AssignDotNode ----------------------------------- 1220 1221 RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1222 { 1223 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); 1224 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); 1225 RegisterID* result = generator.emitNode(value.get(), m_right); 1226 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1227 generator.emitPutById(base.get(), m_ident, result); 1228 return generator.moveToDestinationIfNeeded(dst, result); 1229 } 1230 1231 // ------------------------------ ReadModifyDotNode ----------------------------------- 1232 1233 RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1234 { 1235 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); 1236 1237 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 1238 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); 1239 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1240 1241 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1242 return generator.emitPutById(base.get(), m_ident, updatedValue); 1243 } 1244 1245 // ------------------------------ AssignErrorNode ----------------------------------- 1246 1247 RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1248 { 1249 return emitThrowReferenceError(generator, "Left side of assignment is not a reference."); 1250 } 1251 1252 // ------------------------------ AssignBracketNode ----------------------------------- 1253 1254 RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1255 { 1256 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); 1257 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); 1258 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); 1259 RegisterID* result = generator.emitNode(value.get(), m_right); 1260 1261 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1262 generator.emitPutByVal(base.get(), property.get(), result); 1263 return generator.moveToDestinationIfNeeded(dst, result); 1264 } 1265 1266 // ------------------------------ ReadModifyBracketNode ----------------------------------- 1267 1268 RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1269 { 1270 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); 1271 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); 1272 1273 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 1274 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get()); 1275 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1276 1277 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1278 generator.emitPutByVal(base.get(), property.get(), updatedValue); 1279 1280 return updatedValue; 1281 } 1282 1283 // ------------------------------ CommaNode ------------------------------------ 1284 1285 RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1286 { 1287 ASSERT(m_expressions.size() > 1); 1288 for (size_t i = 0; i < m_expressions.size() - 1; i++) 1289 generator.emitNode(generator.ignoredResult(), m_expressions[i]); 1290 return generator.emitNode(dst, m_expressions.last()); 1291 } 1292 1293 // ------------------------------ ConstDeclNode ------------------------------------ 1294 1295 RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) 1296 { 1297 if (RegisterID* local = generator.constRegisterFor(m_ident)) { 1298 if (!m_init) 1299 return local; 1300 1301 return generator.emitNode(local, m_init); 1302 } 1303 1304 if (generator.codeType() != EvalCode) { 1305 if (m_init) 1306 return generator.emitNode(m_init); 1307 else 1308 return generator.emitResolve(generator.newTemporary(), m_ident); 1309 } 1310 // FIXME: While this code should only be hit in eval code, it will potentially 1311 // assign to the wrong base if m_ident exists in an intervening dynamic scope. 1312 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); 1313 RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined()); 1314 return generator.emitPutById(base.get(), m_ident, value); 1315 } 1316 1317 RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1318 { 1319 RegisterID* result = 0; 1320 for (ConstDeclNode* n = this; n; n = n->m_next) 1321 result = n->emitCodeSingle(generator); 1322 1323 return result; 1324 } 1325 1326 // ------------------------------ ConstStatementNode ----------------------------- 1327 1328 RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1329 { 1330 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1331 return generator.emitNode(m_next); 1332 } 1333 1334 // ------------------------------ SourceElements ------------------------------- 1335 1336 1337 inline StatementNode* SourceElements::lastStatement() const 1338 { 1339 size_t size = m_statements.size(); 1340 return size ? m_statements[size - 1] : 0; 1341 } 1342 1343 inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1344 { 1345 size_t size = m_statements.size(); 1346 for (size_t i = 0; i < size; ++i) 1347 generator.emitNode(dst, m_statements[i]); 1348 } 1349 1350 // ------------------------------ BlockNode ------------------------------------ 1351 1352 inline StatementNode* BlockNode::lastStatement() const 1353 { 1354 return m_statements ? m_statements->lastStatement() : 0; 1355 } 1356 1357 inline StatementNode* BlockNode::singleStatement() const 1358 { 1359 return m_statements ? m_statements->singleStatement() : 0; 1360 } 1361 1362 RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1363 { 1364 if (m_statements) 1365 m_statements->emitBytecode(generator, dst); 1366 return 0; 1367 } 1368 1369 // ------------------------------ EmptyStatementNode --------------------------- 1370 1371 RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1372 { 1373 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1374 return dst; 1375 } 1376 1377 // ------------------------------ DebuggerStatementNode --------------------------- 1378 1379 RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1380 { 1381 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine()); 1382 return dst; 1383 } 1384 1385 // ------------------------------ ExprStatementNode ---------------------------- 1386 1387 RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1388 { 1389 ASSERT(m_expr); 1390 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1391 return generator.emitNode(dst, m_expr); 1392 } 1393 1394 // ------------------------------ VarStatementNode ---------------------------- 1395 1396 RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1397 { 1398 ASSERT(m_expr); 1399 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1400 return generator.emitNode(m_expr); 1401 } 1402 1403 // ------------------------------ IfNode --------------------------------------- 1404 1405 RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1406 { 1407 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1408 1409 RefPtr<Label> afterThen = generator.newLabel(); 1410 1411 if (m_condition->hasConditionContextCodegen()) { 1412 RefPtr<Label> beforeThen = generator.newLabel(); 1413 generator.emitNodeInConditionContext(m_condition, beforeThen.get(), afterThen.get(), true); 1414 generator.emitLabel(beforeThen.get()); 1415 } else { 1416 RegisterID* cond = generator.emitNode(m_condition); 1417 generator.emitJumpIfFalse(cond, afterThen.get()); 1418 } 1419 1420 generator.emitNode(dst, m_ifBlock); 1421 generator.emitLabel(afterThen.get()); 1422 1423 // FIXME: This should return the last statement executed so that it can be returned as a Completion. 1424 return 0; 1425 } 1426 1427 // ------------------------------ IfElseNode --------------------------------------- 1428 1429 RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1430 { 1431 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1432 1433 RefPtr<Label> beforeElse = generator.newLabel(); 1434 RefPtr<Label> afterElse = generator.newLabel(); 1435 1436 if (m_condition->hasConditionContextCodegen()) { 1437 RefPtr<Label> beforeThen = generator.newLabel(); 1438 generator.emitNodeInConditionContext(m_condition, beforeThen.get(), beforeElse.get(), true); 1439 generator.emitLabel(beforeThen.get()); 1440 } else { 1441 RegisterID* cond = generator.emitNode(m_condition); 1442 generator.emitJumpIfFalse(cond, beforeElse.get()); 1443 } 1444 1445 generator.emitNode(dst, m_ifBlock); 1446 generator.emitJump(afterElse.get()); 1447 1448 generator.emitLabel(beforeElse.get()); 1449 1450 generator.emitNode(dst, m_elseBlock); 1451 1452 generator.emitLabel(afterElse.get()); 1453 1454 // FIXME: This should return the last statement executed so that it can be returned as a Completion. 1455 return 0; 1456 } 1457 1458 // ------------------------------ DoWhileNode ---------------------------------- 1459 1460 RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1461 { 1462 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); 1463 1464 RefPtr<Label> topOfLoop = generator.newLabel(); 1465 generator.emitLabel(topOfLoop.get()); 1466 1467 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1468 1469 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); 1470 1471 generator.emitLabel(scope->continueTarget()); 1472 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); 1473 if (m_expr->hasConditionContextCodegen()) 1474 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false); 1475 else { 1476 RegisterID* cond = generator.emitNode(m_expr); 1477 generator.emitJumpIfTrue(cond, topOfLoop.get()); 1478 } 1479 1480 generator.emitLabel(scope->breakTarget()); 1481 return result.get(); 1482 } 1483 1484 // ------------------------------ WhileNode ------------------------------------ 1485 1486 RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1487 { 1488 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); 1489 1490 generator.emitJump(scope->continueTarget()); 1491 1492 RefPtr<Label> topOfLoop = generator.newLabel(); 1493 generator.emitLabel(topOfLoop.get()); 1494 1495 generator.emitNode(dst, m_statement); 1496 1497 generator.emitLabel(scope->continueTarget()); 1498 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); 1499 1500 if (m_expr->hasConditionContextCodegen()) 1501 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false); 1502 else { 1503 RegisterID* cond = generator.emitNode(m_expr); 1504 generator.emitJumpIfTrue(cond, topOfLoop.get()); 1505 } 1506 1507 generator.emitLabel(scope->breakTarget()); 1508 1509 // FIXME: This should return the last statement executed so that it can be returned as a Completion 1510 return 0; 1511 } 1512 1513 // ------------------------------ ForNode -------------------------------------- 1514 1515 RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1516 { 1517 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); 1518 1519 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1520 1521 if (m_expr1) 1522 generator.emitNode(generator.ignoredResult(), m_expr1); 1523 1524 RefPtr<Label> condition = generator.newLabel(); 1525 generator.emitJump(condition.get()); 1526 1527 RefPtr<Label> topOfLoop = generator.newLabel(); 1528 generator.emitLabel(topOfLoop.get()); 1529 1530 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); 1531 1532 generator.emitLabel(scope->continueTarget()); 1533 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1534 if (m_expr3) 1535 generator.emitNode(generator.ignoredResult(), m_expr3); 1536 1537 generator.emitLabel(condition.get()); 1538 if (m_expr2) { 1539 if (m_expr2->hasConditionContextCodegen()) 1540 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), false); 1541 else { 1542 RegisterID* cond = generator.emitNode(m_expr2); 1543 generator.emitJumpIfTrue(cond, topOfLoop.get()); 1544 } 1545 } else 1546 generator.emitJump(topOfLoop.get()); 1547 1548 generator.emitLabel(scope->breakTarget()); 1549 return result.get(); 1550 } 1551 1552 // ------------------------------ ForInNode ------------------------------------ 1553 1554 RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1555 { 1556 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); 1557 1558 if (!m_lexpr->isLocation()) 1559 return emitThrowReferenceError(generator, "Left side of for-in statement is not a reference."); 1560 1561 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1562 1563 if (m_init) 1564 generator.emitNode(generator.ignoredResult(), m_init); 1565 1566 RefPtr<RegisterID> base = generator.newTemporary(); 1567 generator.emitNode(base.get(), m_expr); 1568 RefPtr<RegisterID> i = generator.newTemporary(); 1569 RefPtr<RegisterID> size = generator.newTemporary(); 1570 RefPtr<RegisterID> expectedSubscript; 1571 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget()); 1572 generator.emitJump(scope->continueTarget()); 1573 1574 RefPtr<Label> loopStart = generator.newLabel(); 1575 generator.emitLabel(loopStart.get()); 1576 1577 RegisterID* propertyName; 1578 bool optimizedForinAccess = false; 1579 if (m_lexpr->isResolveNode()) { 1580 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); 1581 propertyName = generator.registerFor(ident); 1582 if (!propertyName) { 1583 propertyName = generator.newTemporary(); 1584 RefPtr<RegisterID> protect = propertyName; 1585 RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), ident); 1586 1587 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1588 generator.emitPutById(base, ident, propertyName); 1589 } else { 1590 expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName); 1591 generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName); 1592 optimizedForinAccess = true; 1593 } 1594 } else if (m_lexpr->isDotAccessorNode()) { 1595 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr); 1596 const Identifier& ident = assignNode->identifier(); 1597 propertyName = generator.newTemporary(); 1598 RefPtr<RegisterID> protect = propertyName; 1599 RegisterID* base = generator.emitNode(assignNode->base()); 1600 1601 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset()); 1602 generator.emitPutById(base, ident, propertyName); 1603 } else { 1604 ASSERT(m_lexpr->isBracketAccessorNode()); 1605 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr); 1606 propertyName = generator.newTemporary(); 1607 RefPtr<RegisterID> protect = propertyName; 1608 RefPtr<RegisterID> base = generator.emitNode(assignNode->base()); 1609 RegisterID* subscript = generator.emitNode(assignNode->subscript()); 1610 1611 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset()); 1612 generator.emitPutByVal(base.get(), subscript, propertyName); 1613 } 1614 1615 generator.emitNode(dst, m_statement); 1616 1617 if (optimizedForinAccess) 1618 generator.popOptimisedForIn(); 1619 1620 generator.emitLabel(scope->continueTarget()); 1621 generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get()); 1622 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1623 generator.emitLabel(scope->breakTarget()); 1624 return dst; 1625 } 1626 1627 // ------------------------------ ContinueNode --------------------------------- 1628 1629 // ECMA 12.7 1630 RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1631 { 1632 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1633 1634 LabelScope* scope = generator.continueTarget(m_ident); 1635 ASSERT(scope); 1636 1637 generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth()); 1638 return dst; 1639 } 1640 1641 // ------------------------------ BreakNode ------------------------------------ 1642 1643 // ECMA 12.8 1644 RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1645 { 1646 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1647 1648 LabelScope* scope = generator.breakTarget(m_ident); 1649 ASSERT(scope); 1650 1651 generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth()); 1652 return dst; 1653 } 1654 1655 // ------------------------------ ReturnNode ----------------------------------- 1656 1657 RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1658 { 1659 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1660 ASSERT(generator.codeType() == FunctionCode); 1661 1662 if (dst == generator.ignoredResult()) 1663 dst = 0; 1664 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined()); 1665 RefPtr<RegisterID> returnRegister; 1666 if (generator.scopeDepth()) { 1667 RefPtr<Label> l0 = generator.newLabel(); 1668 if (generator.hasFinaliser() && !r0->isTemporary()) { 1669 returnRegister = generator.emitMove(generator.newTemporary(), r0); 1670 r0 = returnRegister.get(); 1671 } 1672 generator.emitJumpScopes(l0.get(), 0); 1673 generator.emitLabel(l0.get()); 1674 } 1675 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); 1676 return generator.emitReturn(r0); 1677 } 1678 1679 // ------------------------------ WithNode ------------------------------------- 1680 1681 RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1682 { 1683 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1684 1685 RefPtr<RegisterID> scope = generator.newTemporary(); 1686 generator.emitNode(scope.get(), m_expr); // scope must be protected until popped 1687 generator.emitExpressionInfo(m_divot, m_expressionLength, 0); 1688 generator.emitPushScope(scope.get()); 1689 RegisterID* result = generator.emitNode(dst, m_statement); 1690 generator.emitPopScope(); 1691 return result; 1692 } 1693 1694 // ------------------------------ CaseClauseNode -------------------------------- 1695 1696 inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1697 { 1698 if (m_statements) 1699 m_statements->emitBytecode(generator, dst); 1700 } 1701 1702 // ------------------------------ CaseBlockNode -------------------------------- 1703 1704 enum SwitchKind { 1705 SwitchUnset = 0, 1706 SwitchNumber = 1, 1707 SwitchString = 2, 1708 SwitchNeither = 3 1709 }; 1710 1711 static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num) 1712 { 1713 for (; list; list = list->getNext()) { 1714 ExpressionNode* clauseExpression = list->getClause()->expr(); 1715 literalVector.append(clauseExpression); 1716 if (clauseExpression->isNumber()) { 1717 double value = static_cast<NumberNode*>(clauseExpression)->value(); 1718 int32_t intVal = static_cast<int32_t>(value); 1719 if ((typeForTable & ~SwitchNumber) || (intVal != value)) { 1720 typeForTable = SwitchNeither; 1721 break; 1722 } 1723 if (intVal < min_num) 1724 min_num = intVal; 1725 if (intVal > max_num) 1726 max_num = intVal; 1727 typeForTable = SwitchNumber; 1728 continue; 1729 } 1730 if (clauseExpression->isString()) { 1731 if (typeForTable & ~SwitchString) { 1732 typeForTable = SwitchNeither; 1733 break; 1734 } 1735 const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring(); 1736 if (singleCharacterSwitch &= value.length() == 1) { 1737 int32_t intVal = value.impl()->characters()[0]; 1738 if (intVal < min_num) 1739 min_num = intVal; 1740 if (intVal > max_num) 1741 max_num = intVal; 1742 } 1743 typeForTable = SwitchString; 1744 continue; 1745 } 1746 typeForTable = SwitchNeither; 1747 break; 1748 } 1749 } 1750 1751 SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num) 1752 { 1753 SwitchKind typeForTable = SwitchUnset; 1754 bool singleCharacterSwitch = true; 1755 1756 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); 1757 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); 1758 1759 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither) 1760 return SwitchInfo::SwitchNone; 1761 1762 if (typeForTable == SwitchNumber) { 1763 int32_t range = max_num - min_num; 1764 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10) 1765 return SwitchInfo::SwitchImmediate; 1766 return SwitchInfo::SwitchNone; 1767 } 1768 1769 ASSERT(typeForTable == SwitchString); 1770 1771 if (singleCharacterSwitch) { 1772 int32_t range = max_num - min_num; 1773 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10) 1774 return SwitchInfo::SwitchCharacter; 1775 } 1776 1777 return SwitchInfo::SwitchString; 1778 } 1779 1780 RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst) 1781 { 1782 RefPtr<Label> defaultLabel; 1783 Vector<RefPtr<Label>, 8> labelVector; 1784 Vector<ExpressionNode*, 8> literalVector; 1785 int32_t min_num = std::numeric_limits<int32_t>::max(); 1786 int32_t max_num = std::numeric_limits<int32_t>::min(); 1787 SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num); 1788 1789 if (switchType != SwitchInfo::SwitchNone) { 1790 // Prepare the various labels 1791 for (uint32_t i = 0; i < literalVector.size(); i++) 1792 labelVector.append(generator.newLabel()); 1793 defaultLabel = generator.newLabel(); 1794 generator.beginSwitch(switchExpression, switchType); 1795 } else { 1796 // Setup jumps 1797 for (ClauseListNode* list = m_list1; list; list = list->getNext()) { 1798 RefPtr<RegisterID> clauseVal = generator.newTemporary(); 1799 generator.emitNode(clauseVal.get(), list->getClause()->expr()); 1800 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); 1801 labelVector.append(generator.newLabel()); 1802 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); 1803 } 1804 1805 for (ClauseListNode* list = m_list2; list; list = list->getNext()) { 1806 RefPtr<RegisterID> clauseVal = generator.newTemporary(); 1807 generator.emitNode(clauseVal.get(), list->getClause()->expr()); 1808 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); 1809 labelVector.append(generator.newLabel()); 1810 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); 1811 } 1812 defaultLabel = generator.newLabel(); 1813 generator.emitJump(defaultLabel.get()); 1814 } 1815 1816 RegisterID* result = 0; 1817 1818 size_t i = 0; 1819 for (ClauseListNode* list = m_list1; list; list = list->getNext()) { 1820 generator.emitLabel(labelVector[i++].get()); 1821 list->getClause()->emitBytecode(generator, dst); 1822 } 1823 1824 if (m_defaultClause) { 1825 generator.emitLabel(defaultLabel.get()); 1826 m_defaultClause->emitBytecode(generator, dst); 1827 } 1828 1829 for (ClauseListNode* list = m_list2; list; list = list->getNext()) { 1830 generator.emitLabel(labelVector[i++].get()); 1831 list->getClause()->emitBytecode(generator, dst); 1832 } 1833 if (!m_defaultClause) 1834 generator.emitLabel(defaultLabel.get()); 1835 1836 ASSERT(i == labelVector.size()); 1837 if (switchType != SwitchInfo::SwitchNone) { 1838 ASSERT(labelVector.size() == literalVector.size()); 1839 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num); 1840 } 1841 return result; 1842 } 1843 1844 // ------------------------------ SwitchNode ----------------------------------- 1845 1846 RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1847 { 1848 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1849 1850 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch); 1851 1852 RefPtr<RegisterID> r0 = generator.emitNode(m_expr); 1853 RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst); 1854 1855 generator.emitLabel(scope->breakTarget()); 1856 return r1; 1857 } 1858 1859 // ------------------------------ LabelNode ------------------------------------ 1860 1861 RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1862 { 1863 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1864 1865 ASSERT(!generator.breakTarget(m_name)); 1866 1867 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name); 1868 RegisterID* r0 = generator.emitNode(dst, m_statement); 1869 1870 generator.emitLabel(scope->breakTarget()); 1871 return r0; 1872 } 1873 1874 // ------------------------------ ThrowNode ------------------------------------ 1875 1876 RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1877 { 1878 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1879 1880 if (dst == generator.ignoredResult()) 1881 dst = 0; 1882 RefPtr<RegisterID> expr = generator.emitNode(m_expr); 1883 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 1884 generator.emitThrow(expr.get()); 1885 return 0; 1886 } 1887 1888 // ------------------------------ TryNode -------------------------------------- 1889 1890 RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1891 { 1892 // NOTE: The catch and finally blocks must be labeled explicitly, so the 1893 // optimizer knows they may be jumped to from anywhere. 1894 1895 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 1896 1897 RefPtr<Label> tryStartLabel = generator.newLabel(); 1898 RefPtr<Label> finallyStart; 1899 RefPtr<RegisterID> finallyReturnAddr; 1900 if (m_finallyBlock) { 1901 finallyStart = generator.newLabel(); 1902 finallyReturnAddr = generator.newTemporary(); 1903 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get()); 1904 } 1905 1906 generator.emitLabel(tryStartLabel.get()); 1907 generator.emitNode(dst, m_tryBlock); 1908 1909 if (m_catchBlock) { 1910 RefPtr<Label> catchEndLabel = generator.newLabel(); 1911 1912 // Normal path: jump over the catch block. 1913 generator.emitJump(catchEndLabel.get()); 1914 1915 // Uncaught exception path: the catch block. 1916 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); 1917 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get()); 1918 if (m_catchHasEval) { 1919 RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary()); 1920 generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get()); 1921 generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get()); 1922 generator.emitPushScope(exceptionRegister.get()); 1923 } else 1924 generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get()); 1925 generator.emitNode(dst, m_catchBlock); 1926 generator.emitPopScope(); 1927 generator.emitLabel(catchEndLabel.get()); 1928 } 1929 1930 if (m_finallyBlock) { 1931 generator.popFinallyContext(); 1932 // there may be important registers live at the time we jump 1933 // to a finally block (such as for a return or throw) so we 1934 // ref the highest register ever used as a conservative 1935 // approach to not clobbering anything important 1936 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister(); 1937 RefPtr<Label> finallyEndLabel = generator.newLabel(); 1938 1939 // Normal path: invoke the finally block, then jump over it. 1940 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); 1941 generator.emitJump(finallyEndLabel.get()); 1942 1943 // Uncaught exception path: invoke the finally block, then re-throw the exception. 1944 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); 1945 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get()); 1946 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); 1947 generator.emitThrow(tempExceptionRegister.get()); 1948 1949 // The finally block. 1950 generator.emitLabel(finallyStart.get()); 1951 generator.emitNode(dst, m_finallyBlock); 1952 generator.emitSubroutineReturn(finallyReturnAddr.get()); 1953 1954 generator.emitLabel(finallyEndLabel.get()); 1955 } 1956 1957 return dst; 1958 } 1959 1960 // ------------------------------ ScopeNode ----------------------------- 1961 1962 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst) 1963 { 1964 if (m_data->m_statements) 1965 m_data->m_statements->emitBytecode(generator, dst); 1966 } 1967 1968 // ------------------------------ ProgramNode ----------------------------- 1969 1970 RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1971 { 1972 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); 1973 1974 RefPtr<RegisterID> dstRegister = generator.newTemporary(); 1975 generator.emitLoad(dstRegister.get(), jsUndefined()); 1976 emitStatementsBytecode(generator, dstRegister.get()); 1977 1978 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); 1979 generator.emitEnd(dstRegister.get()); 1980 return 0; 1981 } 1982 1983 // ------------------------------ EvalNode ----------------------------- 1984 1985 RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1986 { 1987 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); 1988 1989 RefPtr<RegisterID> dstRegister = generator.newTemporary(); 1990 generator.emitLoad(dstRegister.get(), jsUndefined()); 1991 emitStatementsBytecode(generator, dstRegister.get()); 1992 1993 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); 1994 generator.emitEnd(dstRegister.get()); 1995 return 0; 1996 } 1997 1998 // ------------------------------ FunctionBodyNode ----------------------------- 1999 2000 RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 2001 { 2002 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); 2003 emitStatementsBytecode(generator, generator.ignoredResult()); 2004 2005 StatementNode* singleStatement = this->singleStatement(); 2006 ReturnNode* returnNode = 0; 2007 2008 // Check for a return statement at the end of a function composed of a single block. 2009 if (singleStatement && singleStatement->isBlock()) { 2010 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement(); 2011 if (lastStatementInBlock && lastStatementInBlock->isReturnNode()) 2012 returnNode = static_cast<ReturnNode*>(lastStatementInBlock); 2013 } 2014 2015 // If there is no return we must automatically insert one. 2016 if (!returnNode) { 2017 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined()); 2018 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); 2019 generator.emitReturn(r0); 2020 return 0; 2021 } 2022 2023 // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare. 2024 if (static_cast<BlockNode*>(singleStatement)->singleStatement()) { 2025 ExpressionNode* returnValueExpression = returnNode->value(); 2026 if (returnValueExpression && returnValueExpression->isSubtract()) { 2027 ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs(); 2028 ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs(); 2029 if (lhsExpression->isResolveNode() && rhsExpression->isResolveNode()) { 2030 generator.setIsNumericCompareFunction(generator.argumentNumberFor(static_cast<ResolveNode*>(lhsExpression)->identifier()) == 1 2031 && generator.argumentNumberFor(static_cast<ResolveNode*>(rhsExpression)->identifier()) == 2); 2032 } 2033 } 2034 } 2035 2036 return 0; 2037 } 2038 2039 // ------------------------------ FuncDeclNode --------------------------------- 2040 2041 RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2042 { 2043 if (dst == generator.ignoredResult()) 2044 dst = 0; 2045 return dst; 2046 } 2047 2048 // ------------------------------ FuncExprNode --------------------------------- 2049 2050 RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2051 { 2052 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this); 2053 } 2054 2055 } // namespace JSC 2056