1/* 2* Copyright (C) 1999-2002 Harri Porten (porten@kde.org) 3* Copyright (C) 2001 Peter Kelly (pmk@post.com) 4* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved. 5* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) 6* Copyright (C) 2007 Maks Orlovich 7* Copyright (C) 2007 Eric Seidel <eric@webkit.org> 8 * Copyright (C) 2012 Igalia, S.L. 9* 10* This library is free software; you can redistribute it and/or 11* modify it under the terms of the GNU Library General Public 12* License as published by the Free Software Foundation; either 13* version 2 of the License, or (at your option) any later version. 14* 15* This library is distributed in the hope that it will be useful, 16* but WITHOUT ANY WARRANTY; without even the implied warranty of 17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18* Library General Public License for more details. 19* 20* You should have received a copy of the GNU Library General Public License 21* along with this library; see the file COPYING.LIB. If not, write to 22* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23* Boston, MA 02110-1301, USA. 24* 25*/ 26 27#include "config.h" 28#include "Nodes.h" 29#include "NodeConstructors.h" 30 31#include "BuiltinNames.h" 32#include "BytecodeGenerator.h" 33#include "CallFrame.h" 34#include "Debugger.h" 35#include "JIT.h" 36#include "JSFunction.h" 37#include "JSGlobalObject.h" 38#include "JSNameScope.h" 39#include "JSONObject.h" 40#include "LabelScope.h" 41#include "Lexer.h" 42#include "JSCInlines.h" 43#include "Parser.h" 44#include "PropertyNameArray.h" 45#include "RegExpCache.h" 46#include "RegExpObject.h" 47#include "SamplingTool.h" 48#include "StackAlignment.h" 49#include <wtf/Assertions.h> 50#include <wtf/RefCountedLeakCounter.h> 51#include <wtf/Threading.h> 52 53using namespace WTF; 54 55namespace JSC { 56 57/* 58 Details of the emitBytecode function. 59 60 Return value: The register holding the production's value. 61 dst: An optional parameter specifying the most efficient destination at 62 which to store the production's value. The callee must honor dst. 63 64 The dst argument provides for a crude form of copy propagation. For example, 65 66 x = 1 67 68 becomes 69 70 load r[x], 1 71 72 instead of 73 74 load r0, 1 75 mov r[x], r0 76 77 because the assignment node, "x =", passes r[x] as dst to the number node, "1". 78*/ 79 80void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode) 81{ 82 RegisterID* result = generator.emitNode(this); 83 if (fallThroughMode == FallThroughMeansTrue) 84 generator.emitJumpIfFalse(result, falseTarget); 85 else 86 generator.emitJumpIfTrue(result, trueTarget); 87} 88 89// ------------------------------ ThrowableExpressionData -------------------------------- 90 91RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message) 92{ 93 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 94 generator.emitThrowReferenceError(message); 95 return generator.newTemporary(); 96} 97 98// ------------------------------ ConstantNode ---------------------------------- 99 100void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode) 101{ 102 TriState value = jsValue(generator).pureToBoolean(); 103 if (value == MixedTriState) 104 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode); 105 else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse) 106 generator.emitJump(trueTarget); 107 else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue) 108 generator.emitJump(falseTarget); 109 110 // All other cases are unconditional fall-throughs, like "if (true)". 111} 112 113RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 114{ 115 if (dst == generator.ignoredResult()) 116 return 0; 117 return generator.emitLoad(dst, jsValue(generator)); 118} 119 120JSValue StringNode::jsValue(BytecodeGenerator& generator) const 121{ 122 return generator.addStringConstant(m_value); 123} 124 125// ------------------------------ RegExpNode ----------------------------------- 126 127RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 128{ 129 if (dst == generator.ignoredResult()) 130 return 0; 131 return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(*generator.vm(), m_pattern.string(), regExpFlags(m_flags.string()))); 132} 133 134// ------------------------------ ThisNode ------------------------------------- 135 136RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 137{ 138 if (dst == generator.ignoredResult()) 139 return 0; 140 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister()); 141} 142 143// ------------------------------ ResolveNode ---------------------------------- 144 145bool ResolveNode::isPure(BytecodeGenerator& generator) const 146{ 147 return generator.local(m_ident).get(); 148} 149 150RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 151{ 152 if (Local local = generator.local(m_ident)) { 153 if (dst == generator.ignoredResult()) 154 return 0; 155 return generator.moveToDestinationIfNeeded(dst, local.get()); 156 } 157 158 JSTextPosition divot = m_start + m_ident.length(); 159 generator.emitExpressionInfo(divot, m_start, divot); 160 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident); 161 return generator.emitGetFromScope(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound); 162} 163 164// ------------------------------ ArrayNode ------------------------------------ 165 166RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 167{ 168 // FIXME: Should we put all of this code into emitNewArray? 169 170 unsigned length = 0; 171 ElementNode* firstPutElement; 172 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) { 173 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression()) 174 break; 175 ++length; 176 } 177 178 if (!firstPutElement && !m_elision) 179 return generator.emitNewArray(generator.finalDestination(dst), m_element, length); 180 181 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length); 182 ElementNode* n = firstPutElement; 183 for (; n; n = n->next()) { 184 if (n->value()->isSpreadExpression()) 185 goto handleSpread; 186 RegisterID* value = generator.emitNode(n->value()); 187 length += n->elision(); 188 generator.emitPutByIndex(array.get(), length++, value); 189 } 190 191 if (m_elision) { 192 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length)); 193 generator.emitPutById(array.get(), generator.propertyNames().length, value); 194 } 195 196 return generator.moveToDestinationIfNeeded(dst, array.get()); 197 198handleSpread: 199 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length)); 200 auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value) 201 { 202 generator.emitDirectPutByVal(array.get(), index.get(), value); 203 generator.emitInc(index.get()); 204 }; 205 for (; n; n = n->next()) { 206 if (n->elision()) 207 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32())); 208 if (n->value()->isSpreadExpression()) { 209 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value()); 210 generator.emitEnumeration(spread, spread->expression(), spreader); 211 } else { 212 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value())); 213 generator.emitInc(index.get()); 214 } 215 } 216 217 if (m_elision) { 218 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32())); 219 generator.emitPutById(array.get(), generator.propertyNames().length, index.get()); 220 } 221 return generator.moveToDestinationIfNeeded(dst, array.get()); 222} 223 224bool ArrayNode::isSimpleArray() const 225{ 226 if (m_elision || m_optional) 227 return false; 228 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) { 229 if (ptr->elision()) 230 return false; 231 } 232 return true; 233} 234 235ArgumentListNode* ArrayNode::toArgumentList(VM* vm, int lineNumber, int startPosition) const 236{ 237 ASSERT(!m_elision && !m_optional); 238 ElementNode* ptr = m_element; 239 if (!ptr) 240 return 0; 241 JSTokenLocation location; 242 location.line = lineNumber; 243 location.startOffset = startPosition; 244 ArgumentListNode* head = new (vm) ArgumentListNode(location, ptr->value()); 245 ArgumentListNode* tail = head; 246 ptr = ptr->next(); 247 for (; ptr; ptr = ptr->next()) { 248 ASSERT(!ptr->elision()); 249 tail = new (vm) ArgumentListNode(location, tail, ptr->value()); 250 } 251 return head; 252} 253 254// ------------------------------ ObjectLiteralNode ---------------------------- 255 256RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 257{ 258 if (!m_list) { 259 if (dst == generator.ignoredResult()) 260 return 0; 261 return generator.emitNewObject(generator.finalDestination(dst)); 262 } 263 return generator.emitNode(dst, m_list); 264} 265 266// ------------------------------ PropertyListNode ----------------------------- 267 268RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 269{ 270 RefPtr<RegisterID> newObj = generator.tempDestination(dst); 271 272 generator.emitNewObject(newObj.get()); 273 274 // Fast case: this loop just handles regular value properties. 275 PropertyListNode* p = this; 276 for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next) { 277 if (p->m_node->m_name) { 278 generator.emitDirectPutById(newObj.get(), *p->m_node->name(), generator.emitNode(p->m_node->m_assign)); 279 continue; 280 } 281 RefPtr<RegisterID> propertyName = generator.emitNode(p->m_node->m_expression); 282 generator.emitDirectPutByVal(newObj.get(), propertyName.get(), generator.emitNode(p->m_node->m_assign)); 283 } 284 285 // Were there any get/set properties? 286 if (p) { 287 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair; 288 typedef HashMap<StringImpl*, GetterSetterPair> GetterSetterMap; 289 GetterSetterMap map; 290 291 // Build a map, pairing get/set values together. 292 for (PropertyListNode* q = p; q; q = q->m_next) { 293 PropertyNode* node = q->m_node; 294 if (node->m_type == PropertyNode::Constant) 295 continue; 296 297 GetterSetterPair pair(node, static_cast<PropertyNode*>(0)); 298 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair); 299 if (!result.isNewEntry) 300 result.iterator->value.second = node; 301 } 302 303 // Iterate over the remaining properties in the list. 304 for (; p; p = p->m_next) { 305 PropertyNode* node = p->m_node; 306 307 // Handle regular values. 308 if (node->m_type == PropertyNode::Constant) { 309 if (node->name()) { 310 generator.emitDirectPutById(newObj.get(), *node->name(), generator.emitNode(node->m_assign)); 311 continue; 312 } 313 RefPtr<RegisterID> propertyName = generator.emitNode(p->m_node->m_expression); 314 generator.emitDirectPutByVal(newObj.get(), propertyName.get(), generator.emitNode(p->m_node->m_assign)); 315 continue; 316 } 317 318 RegisterID* value = generator.emitNode(node->m_assign); 319 320 // This is a get/set property, find its entry in the map. 321 ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter); 322 GetterSetterMap::iterator it = map.find(node->name()->impl()); 323 ASSERT(it != map.end()); 324 GetterSetterPair& pair = it->value; 325 326 // Was this already generated as a part of its partner? 327 if (pair.second == node) 328 continue; 329 330 // Generate the paired node now. 331 RefPtr<RegisterID> getterReg; 332 RefPtr<RegisterID> setterReg; 333 334 if (node->m_type == PropertyNode::Getter) { 335 getterReg = value; 336 if (pair.second) { 337 ASSERT(pair.second->m_type == PropertyNode::Setter); 338 setterReg = generator.emitNode(pair.second->m_assign); 339 } else { 340 setterReg = generator.newTemporary(); 341 generator.emitLoad(setterReg.get(), jsUndefined()); 342 } 343 } else { 344 ASSERT(node->m_type == PropertyNode::Setter); 345 setterReg = value; 346 if (pair.second) { 347 ASSERT(pair.second->m_type == PropertyNode::Getter); 348 getterReg = generator.emitNode(pair.second->m_assign); 349 } else { 350 getterReg = generator.newTemporary(); 351 generator.emitLoad(getterReg.get(), jsUndefined()); 352 } 353 } 354 355 generator.emitPutGetterSetter(newObj.get(), *node->name(), getterReg.get(), setterReg.get()); 356 } 357 } 358 359 return generator.moveToDestinationIfNeeded(dst, newObj.get()); 360} 361 362// ------------------------------ BracketAccessorNode -------------------------------- 363 364RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 365{ 366 if (m_base->isResolveNode() 367 && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier()) 368 && !generator.symbolTable().slowArguments()) { 369 RegisterID* property = generator.emitNode(m_subscript); 370 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 371 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property); 372 } 373 374 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator)); 375 RegisterID* property = generator.emitNode(m_subscript); 376 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 377 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property); 378} 379 380// ------------------------------ DotAccessorNode -------------------------------- 381 382RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 383{ 384 if (m_ident == generator.propertyNames().length) { 385 if (!m_base->isResolveNode()) 386 goto nonArgumentsPath; 387 ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base); 388 if (!generator.willResolveToArguments(resolveNode->identifier())) 389 goto nonArgumentsPath; 390 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 391 return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments()); 392 } 393 394nonArgumentsPath: 395 RegisterID* base = generator.emitNode(m_base); 396 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 397 return generator.emitGetById(generator.finalDestination(dst), base, m_ident); 398} 399 400// ------------------------------ ArgumentListNode ----------------------------- 401 402RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 403{ 404 ASSERT(m_expr); 405 return generator.emitNode(dst, m_expr); 406} 407 408// ------------------------------ NewExprNode ---------------------------------- 409 410RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 411{ 412 ExpectedFunction expectedFunction; 413 if (m_expr->isResolveNode()) 414 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier()); 415 else 416 expectedFunction = NoExpectedFunction; 417 RefPtr<RegisterID> func = generator.emitNode(m_expr); 418 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get()); 419 CallArguments callArguments(generator, m_args); 420 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd()); 421} 422 423CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments) 424 : m_argumentsNode(argumentsNode) 425 , m_padding(0) 426{ 427 if (generator.shouldEmitProfileHooks()) 428 m_profileHookRegister = generator.newTemporary(); 429 430 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register. 431 if (argumentsNode) { 432 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next) 433 ++argumentCountIncludingThis; 434 } 435 436 m_argv.grow(argumentCountIncludingThis); 437 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) { 438 m_argv[i] = generator.newTemporary(); 439 ASSERT(static_cast<size_t>(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() - 1); 440 } 441 442 while (stackOffset() % stackAlignmentRegisters()) { 443 m_argv.insert(0, generator.newTemporary()); 444 m_padding++; 445 } 446} 447 448// ------------------------------ EvalFunctionCallNode ---------------------------------- 449 450RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 451{ 452 if (Local local = generator.local(generator.propertyNames().eval)) { 453 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get()); 454 CallArguments callArguments(generator, m_args); 455 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 456 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd()); 457 } 458 459 RefPtr<RegisterID> func = generator.newTemporary(); 460 CallArguments callArguments(generator, m_args); 461 JSTextPosition newDivot = divotStart() + 4; 462 generator.emitExpressionInfo(newDivot, divotStart(), newDivot); 463 generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval); 464 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound); 465 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd()); 466} 467 468// ------------------------------ FunctionCallValueNode ---------------------------------- 469 470RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 471{ 472 RefPtr<RegisterID> func = generator.emitNode(m_expr); 473 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get()); 474 CallArguments callArguments(generator, m_args); 475 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 476 return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 477} 478 479// ------------------------------ FunctionCallResolveNode ---------------------------------- 480 481RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 482{ 483 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident); 484 485 if (Local local = generator.local(m_ident)) { 486 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get()); 487 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get()); 488 CallArguments callArguments(generator, m_args); 489 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 490 // This passes NoExpectedFunction because we expect that if the function is in a 491 // local variable, then it's not one of our built-in constructors. 492 return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 493 } 494 495 RefPtr<RegisterID> func = generator.newTemporary(); 496 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get()); 497 CallArguments callArguments(generator, m_args); 498 499 JSTextPosition newDivot = divotStart() + m_ident.length(); 500 generator.emitExpressionInfo(newDivot, divotStart(), newDivot); 501 generator.emitResolveScope(callArguments.thisRegister(), m_ident); 502 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound); 503 return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd()); 504} 505 506// ------------------------------ FunctionCallBracketNode ---------------------------------- 507 508RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 509{ 510 RefPtr<RegisterID> base = generator.emitNode(m_base); 511 RegisterID* property = generator.emitNode(m_subscript); 512 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd()); 513 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); 514 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get()); 515 CallArguments callArguments(generator, m_args); 516 generator.emitMove(callArguments.thisRegister(), base.get()); 517 return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 518} 519 520// ------------------------------ FunctionCallDotNode ---------------------------------- 521 522RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 523{ 524 RefPtr<RegisterID> function = generator.tempDestination(dst); 525 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get()); 526 CallArguments callArguments(generator, m_args); 527 generator.emitNode(callArguments.thisRegister(), m_base); 528 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd()); 529 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident); 530 return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 531} 532 533static RegisterID* getArgumentByVal(BytecodeGenerator& generator, ExpressionNode* base, RegisterID* property, RegisterID* dst, JSTextPosition divot, JSTextPosition divotStart, JSTextPosition divotEnd) 534{ 535 if (base->isResolveNode() 536 && generator.willResolveToArguments(static_cast<ResolveNode*>(base)->identifier()) 537 && !generator.symbolTable().slowArguments()) { 538 generator.emitExpressionInfo(divot, divotStart, divotEnd); 539 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property); 540 } 541 return nullptr; 542} 543 544RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 545{ 546 RefPtr<Label> realCall = generator.newLabel(); 547 RefPtr<Label> end = generator.newLabel(); 548 RefPtr<RegisterID> base = generator.emitNode(m_base); 549 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd()); 550 RefPtr<RegisterID> function; 551 bool emitCallCheck = !generator.isBuiltinFunction(); 552 if (emitCallCheck) { 553 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName()); 554 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get()); 555 } 556 RefPtr<RegisterID> returnValue = generator.finalDestination(dst); 557 { 558 if (m_args->m_listNode && m_args->m_listNode->m_expr && m_args->m_listNode->m_expr->isSpreadExpression()) { 559 RefPtr<RegisterID> profileHookRegister; 560 if (generator.shouldEmitProfileHooks()) 561 profileHookRegister = generator.newTemporary(); 562 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr); 563 ExpressionNode* subject = spread->expression(); 564 RefPtr<RegisterID> thisRegister = getArgumentByVal(generator, subject, generator.emitLoad(0, jsNumber(0)), 0, spread->divot(), spread->divotStart(), spread->divotEnd()); 565 RefPtr<RegisterID> argumentsRegister; 566 if (thisRegister) 567 argumentsRegister = generator.uncheckedRegisterForArguments(); 568 else { 569 argumentsRegister = generator.emitNode(subject); 570 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd()); 571 thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0))); 572 } 573 generator.emitCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd()); 574 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) { 575 ArgumentListNode* oldList = m_args->m_listNode; 576 m_args->m_listNode = m_args->m_listNode->m_next; 577 578 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 579 CallArguments callArguments(generator, m_args); 580 generator.emitNode(callArguments.thisRegister(), oldList->m_expr); 581 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 582 m_args->m_listNode = oldList; 583 } else { 584 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 585 CallArguments callArguments(generator, m_args); 586 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 587 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 588 } 589 } 590 if (emitCallCheck) { 591 generator.emitJump(end.get()); 592 generator.emitLabel(realCall.get()); 593 { 594 CallArguments callArguments(generator, m_args); 595 generator.emitMove(callArguments.thisRegister(), base.get()); 596 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 597 } 598 generator.emitLabel(end.get()); 599 } 600 return returnValue.get(); 601} 602 603static bool areTrivialApplyArguments(ArgumentsNode* args) 604{ 605 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next 606 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray()); 607} 608 609RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 610{ 611 // A few simple cases can be trivially handled as ordinary function calls. 612 // function.apply(), function.apply(arg) -> identical to function.call 613 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation 614 bool mayBeCall = areTrivialApplyArguments(m_args); 615 616 RefPtr<Label> realCall = generator.newLabel(); 617 RefPtr<Label> end = generator.newLabel(); 618 RefPtr<RegisterID> base = generator.emitNode(m_base); 619 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd()); 620 RefPtr<RegisterID> function; 621 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get()); 622 bool emitCallCheck = !generator.isBuiltinFunction(); 623 if (emitCallCheck) { 624 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName()); 625 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get()); 626 } 627 if (mayBeCall) { 628 if (m_args->m_listNode && m_args->m_listNode->m_expr) { 629 ArgumentListNode* oldList = m_args->m_listNode; 630 if (m_args->m_listNode->m_expr->isSpreadExpression()) { 631 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr); 632 RefPtr<RegisterID> profileHookRegister; 633 if (generator.shouldEmitProfileHooks()) 634 profileHookRegister = generator.newTemporary(); 635 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get()); 636 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0)); 637 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined()); 638 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined()); 639 640 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value) 641 { 642 RefPtr<Label> haveThis = generator.newLabel(); 643 RefPtr<Label> end = generator.newLabel(); 644 RefPtr<RegisterID> compareResult = generator.newTemporary(); 645 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32())); 646 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get()); 647 generator.emitMove(thisRegister.get(), value); 648 generator.emitLoad(index.get(), jsNumber(1)); 649 generator.emitJump(end.get()); 650 generator.emitLabel(haveThis.get()); 651 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32())); 652 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get()); 653 generator.emitMove(argumentsRegister.get(), value); 654 generator.emitLoad(index.get(), jsNumber(2)); 655 generator.emitLabel(end.get()); 656 }; 657 generator.emitEnumeration(this, spread->expression(), extractor); 658 generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd()); 659 } else if (m_args->m_listNode->m_next) { 660 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray()); 661 ASSERT(!m_args->m_listNode->m_next->m_next); 662 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.vm(), 0, 0); 663 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 664 CallArguments callArguments(generator, m_args); 665 generator.emitNode(callArguments.thisRegister(), oldList->m_expr); 666 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 667 } else { 668 m_args->m_listNode = m_args->m_listNode->m_next; 669 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 670 CallArguments callArguments(generator, m_args); 671 generator.emitNode(callArguments.thisRegister(), oldList->m_expr); 672 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 673 } 674 m_args->m_listNode = oldList; 675 } else { 676 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 677 CallArguments callArguments(generator, m_args); 678 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 679 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 680 } 681 } else { 682 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next); 683 RefPtr<RegisterID> profileHookRegister; 684 if (generator.shouldEmitProfileHooks()) 685 profileHookRegister = generator.newTemporary(); 686 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 687 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr); 688 RefPtr<RegisterID> argsRegister; 689 ArgumentListNode* args = m_args->m_listNode->m_next; 690 if (args->m_expr->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(args->m_expr)->identifier()) && !generator.symbolTable().slowArguments()) 691 argsRegister = generator.uncheckedRegisterForArguments(); 692 else 693 argsRegister = generator.emitNode(args->m_expr); 694 695 // Function.prototype.apply ignores extra arguments, but we still 696 // need to evaluate them for side effects. 697 while ((args = args->m_next)) 698 generator.emitNode(args->m_expr); 699 700 generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd()); 701 } 702 if (emitCallCheck) { 703 generator.emitJump(end.get()); 704 generator.emitLabel(realCall.get()); 705 CallArguments callArguments(generator, m_args); 706 generator.emitMove(callArguments.thisRegister(), base.get()); 707 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 708 generator.emitLabel(end.get()); 709 } 710 return returnValue.get(); 711} 712 713// ------------------------------ PostfixNode ---------------------------------- 714 715static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper) 716{ 717 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst); 718} 719 720static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper) 721{ 722 if (dst == srcDst) 723 return generator.emitToNumber(generator.finalDestination(dst), srcDst); 724 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst); 725 emitIncOrDec(generator, srcDst, oper); 726 return generator.moveToDestinationIfNeeded(dst, tmp.get()); 727} 728 729RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst) 730{ 731 if (dst == generator.ignoredResult()) 732 return PrefixNode::emitResolve(generator, dst); 733 734 ASSERT(m_expr->isResolveNode()); 735 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr); 736 const Identifier& ident = resolve->identifier(); 737 738 if (Local local = generator.local(ident)) { 739 RegisterID* localReg = local.get(); 740 if (local.isReadOnly()) { 741 generator.emitReadOnlyExceptionIfNeeded(); 742 localReg = generator.emitMove(generator.tempDestination(dst), localReg); 743 } else if (local.isCaptured()) { 744 RefPtr<RegisterID> tempDst = generator.finalDestination(dst); 745 ASSERT(dst != localReg); 746 RefPtr<RegisterID> tempDstSrc = generator.newTemporary(); 747 generator.emitToNumber(tempDst.get(), localReg); 748 generator.emitMove(tempDstSrc.get(), localReg); 749 emitIncOrDec(generator, tempDstSrc.get(), m_operator); 750 generator.emitMove(localReg, tempDstSrc.get()); 751 return tempDst.get(); 752 } 753 return emitPostIncOrDec(generator, generator.finalDestination(dst), localReg, m_operator); 754 } 755 756 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 757 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), ident); 758 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound); 759 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); 760 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound); 761 return oldValue.get(); 762} 763 764RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst) 765{ 766 if (dst == generator.ignoredResult()) 767 return PrefixNode::emitBracket(generator, dst); 768 769 ASSERT(m_expr->isBracketAccessorNode()); 770 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr); 771 ExpressionNode* baseNode = bracketAccessor->base(); 772 ExpressionNode* subscript = bracketAccessor->subscript(); 773 774 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator)); 775 RefPtr<RegisterID> property = generator.emitNode(subscript); 776 777 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd()); 778 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get()); 779 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator); 780 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 781 generator.emitPutByVal(base.get(), property.get(), value.get()); 782 return generator.moveToDestinationIfNeeded(dst, oldValue); 783} 784 785RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst) 786{ 787 if (dst == generator.ignoredResult()) 788 return PrefixNode::emitDot(generator, dst); 789 790 ASSERT(m_expr->isDotAccessorNode()); 791 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr); 792 ExpressionNode* baseNode = dotAccessor->base(); 793 const Identifier& ident = dotAccessor->identifier(); 794 795 RefPtr<RegisterID> base = generator.emitNode(baseNode); 796 797 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd()); 798 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), ident); 799 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator); 800 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 801 generator.emitPutById(base.get(), ident, value.get()); 802 return generator.moveToDestinationIfNeeded(dst, oldValue); 803} 804 805RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 806{ 807 if (m_expr->isResolveNode()) 808 return emitResolve(generator, dst); 809 810 if (m_expr->isBracketAccessorNode()) 811 return emitBracket(generator, dst); 812 813 if (m_expr->isDotAccessorNode()) 814 return emitDot(generator, dst); 815 816 return emitThrowReferenceError(generator, m_operator == OpPlusPlus 817 ? "Postfix ++ operator applied to value that is not a reference." 818 : "Postfix -- operator applied to value that is not a reference."); 819} 820 821// ------------------------------ DeleteResolveNode ----------------------------------- 822 823RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 824{ 825 if (generator.local(m_ident).get()) 826 return generator.emitLoad(generator.finalDestination(dst), false); 827 828 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 829 RefPtr<RegisterID> base = generator.emitResolveScope(generator.tempDestination(dst), m_ident); 830 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident); 831} 832 833// ------------------------------ DeleteBracketNode ----------------------------------- 834 835RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 836{ 837 RefPtr<RegisterID> r0 = generator.emitNode(m_base); 838 RegisterID* r1 = generator.emitNode(m_subscript); 839 840 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 841 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1); 842} 843 844// ------------------------------ DeleteDotNode ----------------------------------- 845 846RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 847{ 848 RegisterID* r0 = generator.emitNode(m_base); 849 850 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 851 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident); 852} 853 854// ------------------------------ DeleteValueNode ----------------------------------- 855 856RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 857{ 858 generator.emitNode(generator.ignoredResult(), m_expr); 859 860 // delete on a non-location expression ignores the value and returns true 861 return generator.emitLoad(generator.finalDestination(dst), true); 862} 863 864// ------------------------------ VoidNode ------------------------------------- 865 866RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 867{ 868 if (dst == generator.ignoredResult()) { 869 generator.emitNode(generator.ignoredResult(), m_expr); 870 return 0; 871 } 872 RefPtr<RegisterID> r0 = generator.emitNode(m_expr); 873 return generator.emitLoad(dst, jsUndefined()); 874} 875 876// ------------------------------ TypeOfValueNode ----------------------------------- 877 878RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 879{ 880 if (Local local = generator.local(m_ident)) { 881 if (dst == generator.ignoredResult()) 882 return 0; 883 return generator.emitTypeOf(generator.finalDestination(dst), local.get()); 884 } 885 886 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident); 887 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound); 888 if (dst == generator.ignoredResult()) 889 return 0; 890 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get()); 891} 892 893// ------------------------------ TypeOfValueNode ----------------------------------- 894 895RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 896{ 897 if (dst == generator.ignoredResult()) { 898 generator.emitNode(generator.ignoredResult(), m_expr); 899 return 0; 900 } 901 RefPtr<RegisterID> src = generator.emitNode(m_expr); 902 return generator.emitTypeOf(generator.finalDestination(dst), src.get()); 903} 904 905// ------------------------------ PrefixNode ---------------------------------- 906 907RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst) 908{ 909 ASSERT(m_expr->isResolveNode()); 910 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr); 911 const Identifier& ident = resolve->identifier(); 912 913 if (Local local = generator.local(ident)) { 914 RegisterID* localReg = local.get(); 915 if (local.isReadOnly()) { 916 generator.emitReadOnlyExceptionIfNeeded(); 917 localReg = generator.emitMove(generator.tempDestination(dst), localReg); 918 } else if (local.isCaptured()) { 919 RefPtr<RegisterID> tempDst = generator.tempDestination(dst); 920 generator.emitMove(tempDst.get(), localReg); 921 emitIncOrDec(generator, tempDst.get(), m_operator); 922 generator.emitMove(localReg, tempDst.get()); 923 return generator.moveToDestinationIfNeeded(dst, tempDst.get()); 924 } 925 emitIncOrDec(generator, localReg, m_operator); 926 return generator.moveToDestinationIfNeeded(dst, localReg); 927 } 928 929 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 930 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), ident); 931 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound); 932 emitIncOrDec(generator, value.get(), m_operator); 933 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound); 934 return generator.moveToDestinationIfNeeded(dst, value.get()); 935} 936 937RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst) 938{ 939 ASSERT(m_expr->isBracketAccessorNode()); 940 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr); 941 ExpressionNode* baseNode = bracketAccessor->base(); 942 ExpressionNode* subscript = bracketAccessor->subscript(); 943 944 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator)); 945 RefPtr<RegisterID> property = generator.emitNode(subscript); 946 RefPtr<RegisterID> propDst = generator.tempDestination(dst); 947 948 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd()); 949 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get()); 950 emitIncOrDec(generator, value, m_operator); 951 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 952 generator.emitPutByVal(base.get(), property.get(), value); 953 return generator.moveToDestinationIfNeeded(dst, propDst.get()); 954} 955 956RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst) 957{ 958 ASSERT(m_expr->isDotAccessorNode()); 959 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr); 960 ExpressionNode* baseNode = dotAccessor->base(); 961 const Identifier& ident = dotAccessor->identifier(); 962 963 RefPtr<RegisterID> base = generator.emitNode(baseNode); 964 RefPtr<RegisterID> propDst = generator.tempDestination(dst); 965 966 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd()); 967 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), ident); 968 emitIncOrDec(generator, value, m_operator); 969 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 970 generator.emitPutById(base.get(), ident, value); 971 return generator.moveToDestinationIfNeeded(dst, propDst.get()); 972} 973 974RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 975{ 976 if (m_expr->isResolveNode()) 977 return emitResolve(generator, dst); 978 979 if (m_expr->isBracketAccessorNode()) 980 return emitBracket(generator, dst); 981 982 if (m_expr->isDotAccessorNode()) 983 return emitDot(generator, dst); 984 985 return emitThrowReferenceError(generator, m_operator == OpPlusPlus 986 ? "Prefix ++ operator applied to value that is not a reference." 987 : "Prefix -- operator applied to value that is not a reference."); 988} 989 990// ------------------------------ Unary Operation Nodes ----------------------------------- 991 992RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 993{ 994 RegisterID* src = generator.emitNode(m_expr); 995 generator.emitExpressionInfo(position(), position(), position()); 996 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src); 997} 998 999// ------------------------------ BitwiseNotNode ----------------------------------- 1000 1001RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1002{ 1003 RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1)); 1004 RegisterID* src1 = generator.emitNode(m_expr); 1005 return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1), src1, src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32())); 1006} 1007 1008// ------------------------------ LogicalNotNode ----------------------------------- 1009 1010void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode) 1011{ 1012 // reverse the true and false targets 1013 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode)); 1014} 1015 1016 1017// ------------------------------ Binary Operation Nodes ----------------------------------- 1018 1019// BinaryOpNode::emitStrcat: 1020// 1021// This node generates an op_strcat operation. This opcode can handle concatenation of three or 1022// more values, where we can determine a set of separate op_add operations would be operating on 1023// string values. 1024// 1025// This function expects to be operating on a graph of AST nodes looking something like this: 1026// 1027// (a)... (b) 1028// \ / 1029// (+) (c) 1030// \ / 1031// [d] ((+)) 1032// \ / 1033// [+=] 1034// 1035// The assignment operation is optional, if it exists the register holding the value on the 1036// lefthand side of the assignment should be passing as the optional 'lhs' argument. 1037// 1038// The method should be called on the node at the root of the tree of regular binary add 1039// operations (marked in the diagram with a double set of parentheses). This node must 1040// be performing a string concatenation (determined by statically detecting that at least 1041// one child must be a string). 1042// 1043// Since the minimum number of values being concatenated together is expected to be 3, if 1044// a lhs to a concatenating assignment is not provided then the root add should have at 1045// least one left child that is also an add that can be determined to be operating on strings. 1046// 1047RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe) 1048{ 1049 ASSERT(isAdd()); 1050 ASSERT(resultDescriptor().definitelyIsString()); 1051 1052 // Create a list of expressions for all the adds in the tree of nodes we can convert into 1053 // a string concatenation. The rightmost node (c) is added first. The rightmost node is 1054 // added first, and the leftmost child is never added, so the vector produced for the 1055 // example above will be [ c, b ]. 1056 Vector<ExpressionNode*, 16> reverseExpressionList; 1057 reverseExpressionList.append(m_expr2); 1058 1059 // Examine the left child of the add. So long as this is a string add, add its right-child 1060 // to the list, and keep processing along the left fork. 1061 ExpressionNode* leftMostAddChild = m_expr1; 1062 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) { 1063 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2); 1064 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1; 1065 } 1066 1067 Vector<RefPtr<RegisterID>, 16> temporaryRegisters; 1068 1069 // If there is an assignment, allocate a temporary to hold the lhs after conversion. 1070 // We could possibly avoid this (the lhs is converted last anyway, we could let the 1071 // op_strcat node handle its conversion if required). 1072 if (lhs) 1073 temporaryRegisters.append(generator.newTemporary()); 1074 1075 // Emit code for the leftmost node ((a) in the example). 1076 temporaryRegisters.append(generator.newTemporary()); 1077 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get(); 1078 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild); 1079 1080 // Note on ordering of conversions: 1081 // 1082 // We maintain the same ordering of conversions as we would see if the concatenations 1083 // was performed as a sequence of adds (otherwise this optimization could change 1084 // behaviour should an object have been provided a valueOf or toString method). 1085 // 1086 // Considering the above example, the sequnce of execution is: 1087 // * evaluate operand (a) 1088 // * evaluate operand (b) 1089 // * convert (a) to primitive <- (this would be triggered by the first add) 1090 // * convert (b) to primitive <- (ditto) 1091 // * evaluate operand (c) 1092 // * convert (c) to primitive <- (this would be triggered by the second add) 1093 // And optionally, if there is an assignment: 1094 // * convert (d) to primitive <- (this would be triggered by the assigning addition) 1095 // 1096 // As such we do not plant an op to convert the leftmost child now. Instead, use 1097 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion 1098 // once the second node has been generated. However, if the leftmost child is an 1099 // immediate we can trivially determine that no conversion will be required. 1100 // If this is the case 1101 if (leftMostAddChild->isString()) 1102 leftMostAddChildTempRegister = 0; 1103 1104 while (reverseExpressionList.size()) { 1105 ExpressionNode* node = reverseExpressionList.last(); 1106 reverseExpressionList.removeLast(); 1107 1108 // Emit the code for the current node. 1109 temporaryRegisters.append(generator.newTemporary()); 1110 generator.emitNode(temporaryRegisters.last().get(), node); 1111 1112 // On the first iteration of this loop, when we first reach this point we have just 1113 // generated the second node, which means it is time to convert the leftmost operand. 1114 if (leftMostAddChildTempRegister) { 1115 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister); 1116 leftMostAddChildTempRegister = 0; // Only do this once. 1117 } 1118 // Plant a conversion for this node, if necessary. 1119 if (!node->isString()) 1120 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get()); 1121 } 1122 ASSERT(temporaryRegisters.size() >= 3); 1123 1124 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. 1125 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. 1126 if (emitExpressionInfoForMe) 1127 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd()); 1128 // If there is an assignment convert the lhs now. This will also copy lhs to 1129 // the temporary register we allocated for it. 1130 if (lhs) 1131 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs); 1132 1133 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size()); 1134} 1135 1136void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode) 1137{ 1138 TriState branchCondition; 1139 ExpressionNode* branchExpression; 1140 tryFoldToBranch(generator, branchCondition, branchExpression); 1141 1142 if (branchCondition == MixedTriState) 1143 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode); 1144 else if (branchCondition == TrueTriState) 1145 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode); 1146 else 1147 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode)); 1148} 1149 1150static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant) 1151{ 1152 ResultType expressionType = branchExpression->resultDescriptor(); 1153 1154 if (expressionType.definitelyIsBoolean() && constant.isBoolean()) 1155 return true; 1156 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1)) 1157 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch. 1158 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0) 1159 return true; 1160 1161 return false; 1162} 1163 1164void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression) 1165{ 1166 branchCondition = MixedTriState; 1167 branchExpression = 0; 1168 1169 ConstantNode* constant = 0; 1170 if (m_expr1->isConstant()) { 1171 constant = static_cast<ConstantNode*>(m_expr1); 1172 branchExpression = m_expr2; 1173 } else if (m_expr2->isConstant()) { 1174 constant = static_cast<ConstantNode*>(m_expr2); 1175 branchExpression = m_expr1; 1176 } 1177 1178 if (!constant) 1179 return; 1180 ASSERT(branchExpression); 1181 1182 OpcodeID opcodeID = this->opcodeID(); 1183 JSValue value = constant->jsValue(generator); 1184 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value); 1185 if (!canFoldToBranch) 1186 return; 1187 1188 if (opcodeID == op_eq || opcodeID == op_stricteq) 1189 branchCondition = triState(value.pureToBoolean()); 1190 else if (opcodeID == op_neq || opcodeID == op_nstricteq) 1191 branchCondition = triState(!value.pureToBoolean()); 1192} 1193 1194RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1195{ 1196 OpcodeID opcodeID = this->opcodeID(); 1197 1198 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) { 1199 generator.emitExpressionInfo(position(), position(), position()); 1200 return emitStrcat(generator, dst); 1201 } 1202 1203 if (opcodeID == op_neq) { 1204 if (m_expr1->isNull() || m_expr2->isNull()) { 1205 RefPtr<RegisterID> src = generator.tempDestination(dst); 1206 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); 1207 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get()); 1208 } 1209 } 1210 1211 ExpressionNode* left = m_expr1; 1212 ExpressionNode* right = m_expr2; 1213 if (opcodeID == op_neq || opcodeID == op_nstricteq) { 1214 if (left->isString()) 1215 std::swap(left, right); 1216 } 1217 1218 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator)); 1219 bool wasTypeof = generator.m_lastOpcodeID == op_typeof; 1220 RegisterID* src2 = generator.emitNode(right); 1221 generator.emitExpressionInfo(position(), position(), position()); 1222 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) { 1223 RefPtr<RegisterID> tmp = generator.tempDestination(dst); 1224 if (opcodeID == op_neq) 1225 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2); 1226 else if (opcodeID == op_nstricteq) 1227 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2); 1228 else 1229 RELEASE_ASSERT_NOT_REACHED(); 1230 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get()); 1231 } 1232 RegisterID* result = generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(left->resultDescriptor(), right->resultDescriptor())); 1233 if (opcodeID == op_urshift && dst != generator.ignoredResult()) 1234 return generator.emitUnaryOp(op_unsigned, result, result); 1235 return result; 1236} 1237 1238RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1239{ 1240 if (m_expr1->isNull() || m_expr2->isNull()) { 1241 RefPtr<RegisterID> src = generator.tempDestination(dst); 1242 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); 1243 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get()); 1244 } 1245 1246 ExpressionNode* left = m_expr1; 1247 ExpressionNode* right = m_expr2; 1248 if (left->isString()) 1249 std::swap(left, right); 1250 1251 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator)); 1252 RegisterID* src2 = generator.emitNode(right); 1253 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2); 1254} 1255 1256RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1257{ 1258 ExpressionNode* left = m_expr1; 1259 ExpressionNode* right = m_expr2; 1260 if (left->isString()) 1261 std::swap(left, right); 1262 1263 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator)); 1264 RegisterID* src2 = generator.emitNode(right); 1265 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2); 1266} 1267 1268RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1269{ 1270 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); 1271 RegisterID* src2 = generator.emitNode(m_expr2); 1272 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1273 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); 1274} 1275 1276RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1277{ 1278 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); 1279 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2); 1280 RefPtr<RegisterID> prototype = generator.newTemporary(); 1281 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get()); 1282 RefPtr<Label> target = generator.newLabel(); 1283 1284 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1285 generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get()); 1286 1287 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1288 generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype); 1289 1290 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1291 RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get()); 1292 generator.emitLabel(target.get()); 1293 return result; 1294} 1295 1296// ------------------------------ LogicalOpNode ---------------------------- 1297 1298RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1299{ 1300 RefPtr<RegisterID> temp = generator.tempDestination(dst); 1301 RefPtr<Label> target = generator.newLabel(); 1302 1303 generator.emitNode(temp.get(), m_expr1); 1304 if (m_operator == OpLogicalAnd) 1305 generator.emitJumpIfFalse(temp.get(), target.get()); 1306 else 1307 generator.emitJumpIfTrue(temp.get(), target.get()); 1308 generator.emitNode(temp.get(), m_expr2); 1309 generator.emitLabel(target.get()); 1310 1311 return generator.moveToDestinationIfNeeded(dst, temp.get()); 1312} 1313 1314void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode) 1315{ 1316 RefPtr<Label> afterExpr1 = generator.newLabel(); 1317 if (m_operator == OpLogicalAnd) 1318 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue); 1319 else 1320 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse); 1321 generator.emitLabel(afterExpr1.get()); 1322 1323 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode); 1324} 1325 1326// ------------------------------ ConditionalNode ------------------------------ 1327 1328RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1329{ 1330 RefPtr<RegisterID> newDst = generator.finalDestination(dst); 1331 RefPtr<Label> beforeElse = generator.newLabel(); 1332 RefPtr<Label> afterElse = generator.newLabel(); 1333 1334 RefPtr<Label> beforeThen = generator.newLabel(); 1335 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue); 1336 generator.emitLabel(beforeThen.get()); 1337 1338 generator.emitNode(newDst.get(), m_expr1); 1339 generator.emitJump(afterElse.get()); 1340 1341 generator.emitLabel(beforeElse.get()); 1342 generator.emitNode(newDst.get(), m_expr2); 1343 1344 generator.emitLabel(afterElse.get()); 1345 1346 return newDst.get(); 1347} 1348 1349// ------------------------------ ReadModifyResolveNode ----------------------------------- 1350 1351// FIXME: should this be moved to be a method on BytecodeGenerator? 1352static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0) 1353{ 1354 OpcodeID opcodeID; 1355 switch (oper) { 1356 case OpMultEq: 1357 opcodeID = op_mul; 1358 break; 1359 case OpDivEq: 1360 opcodeID = op_div; 1361 break; 1362 case OpPlusEq: 1363 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString()) 1364 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe); 1365 opcodeID = op_add; 1366 break; 1367 case OpMinusEq: 1368 opcodeID = op_sub; 1369 break; 1370 case OpLShift: 1371 opcodeID = op_lshift; 1372 break; 1373 case OpRShift: 1374 opcodeID = op_rshift; 1375 break; 1376 case OpURShift: 1377 opcodeID = op_urshift; 1378 break; 1379 case OpAndEq: 1380 opcodeID = op_bitand; 1381 break; 1382 case OpXOrEq: 1383 opcodeID = op_bitxor; 1384 break; 1385 case OpOrEq: 1386 opcodeID = op_bitor; 1387 break; 1388 case OpModEq: 1389 opcodeID = op_mod; 1390 break; 1391 default: 1392 RELEASE_ASSERT_NOT_REACHED(); 1393 return dst; 1394 } 1395 1396 RegisterID* src2 = generator.emitNode(m_right); 1397 1398 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. 1399 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. 1400 if (emitExpressionInfoForMe) 1401 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd()); 1402 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types); 1403 if (oper == OpURShift) 1404 return generator.emitUnaryOp(op_unsigned, result, result); 1405 return result; 1406} 1407 1408RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1409{ 1410 if (Local local = generator.local(m_ident)) { 1411 if (local.isReadOnly()) { 1412 generator.emitReadOnlyExceptionIfNeeded(); 1413 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1414 } 1415 1416 if (local.isCaptured() 1417 || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { 1418 RefPtr<RegisterID> result = generator.newTemporary(); 1419 generator.emitMove(result.get(), local.get()); 1420 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1421 generator.emitMove(local.get(), result.get()); 1422 return generator.moveToDestinationIfNeeded(dst, result.get()); 1423 } 1424 1425 RegisterID* result = emitReadModifyAssignment(generator, local.get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1426 return generator.moveToDestinationIfNeeded(dst, result); 1427 } 1428 1429 JSTextPosition newDivot = divotStart() + m_ident.length(); 1430 generator.emitExpressionInfo(newDivot, divotStart(), newDivot); 1431 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident); 1432 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound); 1433 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); 1434 return generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound); 1435} 1436 1437// ------------------------------ AssignResolveNode ----------------------------------- 1438 1439RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1440{ 1441 if (Local local = generator.local(m_ident)) { 1442 if (local.isReadOnly()) { 1443 generator.emitReadOnlyExceptionIfNeeded(); 1444 return generator.emitNode(dst, m_right); 1445 } 1446 if (local.isCaptured()) { 1447 RefPtr<RegisterID> tempDst = generator.tempDestination(dst); 1448 generator.emitNode(tempDst.get(), m_right); 1449 generator.emitMove(local.get(), tempDst.get()); 1450 return generator.moveToDestinationIfNeeded(dst, tempDst.get()); 1451 } 1452 RegisterID* result = generator.emitNode(local.get(), m_right); 1453 return generator.moveToDestinationIfNeeded(dst, result); 1454 } 1455 1456 if (generator.isStrictMode()) 1457 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1458 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident); 1459 if (dst == generator.ignoredResult()) 1460 dst = 0; 1461 RefPtr<RegisterID> result = generator.emitNode(dst, m_right); 1462 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1463 return generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 1464} 1465 1466// ------------------------------ AssignDotNode ----------------------------------- 1467 1468RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1469{ 1470 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); 1471 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); 1472 RegisterID* result = generator.emitNode(value.get(), m_right); 1473 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1474 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result); 1475 generator.emitPutById(base.get(), m_ident, forwardResult); 1476 return generator.moveToDestinationIfNeeded(dst, forwardResult); 1477} 1478 1479// ------------------------------ ReadModifyDotNode ----------------------------------- 1480 1481RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1482{ 1483 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); 1484 1485 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd()); 1486 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); 1487 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, static_cast<JSC::Operator>(m_operator), OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1488 1489 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1490 return generator.emitPutById(base.get(), m_ident, updatedValue); 1491} 1492 1493// ------------------------------ AssignErrorNode ----------------------------------- 1494 1495RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1496{ 1497 return emitThrowReferenceError(generator, "Left side of assignment is not a reference."); 1498} 1499 1500// ------------------------------ AssignBracketNode ----------------------------------- 1501 1502RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1503{ 1504 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); 1505 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); 1506 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); 1507 RegisterID* result = generator.emitNode(value.get(), m_right); 1508 1509 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1510 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result); 1511 generator.emitPutByVal(base.get(), property.get(), forwardResult); 1512 return generator.moveToDestinationIfNeeded(dst, forwardResult); 1513} 1514 1515// ------------------------------ ReadModifyBracketNode ----------------------------------- 1516 1517RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1518{ 1519 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); 1520 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); 1521 1522 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd()); 1523 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get()); 1524 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, static_cast<JSC::Operator>(m_operator), OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1525 1526 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1527 generator.emitPutByVal(base.get(), property.get(), updatedValue); 1528 1529 return updatedValue; 1530} 1531 1532// ------------------------------ CommaNode ------------------------------------ 1533 1534RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1535{ 1536 ASSERT(m_expressions.size() > 1); 1537 for (size_t i = 0; i < m_expressions.size() - 1; i++) 1538 generator.emitNode(generator.ignoredResult(), m_expressions[i]); 1539 return generator.emitNode(dst, m_expressions.last()); 1540} 1541 1542// ------------------------------ ConstDeclNode ------------------------------------ 1543 1544RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) 1545{ 1546 // FIXME: This code does not match the behavior of const in Firefox. 1547 if (Local local = generator.constLocal(m_ident)) { 1548 if (!m_init) 1549 return local.get(); 1550 1551 if (local.isCaptured()) { 1552 RefPtr<RegisterID> tempDst = generator.newTemporary(); 1553 generator.emitNode(tempDst.get(), m_init); 1554 return generator.emitMove(local.get(), tempDst.get()); 1555 } 1556 1557 return generator.emitNode(local.get(), m_init); 1558 } 1559 1560 RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined()); 1561 1562 if (generator.codeType() == GlobalCode) 1563 return generator.emitInitGlobalConst(m_ident, value.get()); 1564 1565 if (generator.codeType() != EvalCode) 1566 return value.get(); 1567 1568 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope. 1569 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident); 1570 return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound); 1571} 1572 1573RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1574{ 1575 RegisterID* result = 0; 1576 for (ConstDeclNode* n = this; n; n = n->m_next) 1577 result = n->emitCodeSingle(generator); 1578 1579 return result; 1580} 1581 1582// ------------------------------ ConstStatementNode ----------------------------- 1583 1584void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1585{ 1586 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1587 generator.emitNode(m_next); 1588} 1589 1590// ------------------------------ SourceElements ------------------------------- 1591 1592 1593inline StatementNode* SourceElements::lastStatement() const 1594{ 1595 size_t size = m_statements.size(); 1596 return size ? m_statements[size - 1] : 0; 1597} 1598 1599inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1600{ 1601 size_t size = m_statements.size(); 1602 for (size_t i = 0; i < size; ++i) 1603 generator.emitNode(dst, m_statements[i]); 1604} 1605 1606// ------------------------------ BlockNode ------------------------------------ 1607 1608inline StatementNode* BlockNode::lastStatement() const 1609{ 1610 return m_statements ? m_statements->lastStatement() : 0; 1611} 1612 1613inline StatementNode* BlockNode::singleStatement() const 1614{ 1615 return m_statements ? m_statements->singleStatement() : 0; 1616} 1617 1618void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1619{ 1620 if (!m_statements) 1621 return; 1622 m_statements->emitBytecode(generator, dst); 1623} 1624 1625// ------------------------------ EmptyStatementNode --------------------------- 1626 1627void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1628{ 1629 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1630} 1631 1632// ------------------------------ DebuggerStatementNode --------------------------- 1633 1634void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1635{ 1636 generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset()); 1637} 1638 1639// ------------------------------ ExprStatementNode ---------------------------- 1640 1641void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1642{ 1643 ASSERT(m_expr); 1644 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1645 generator.emitNode(dst, m_expr); 1646} 1647 1648// ------------------------------ VarStatementNode ---------------------------- 1649 1650void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1651{ 1652 ASSERT(m_expr); 1653 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1654 generator.emitNode(m_expr); 1655} 1656 1657// ------------------------------ IfElseNode --------------------------------------- 1658 1659static inline StatementNode* singleStatement(StatementNode* statementNode) 1660{ 1661 if (statementNode->isBlock()) 1662 return static_cast<BlockNode*>(statementNode)->singleStatement(); 1663 return statementNode; 1664} 1665 1666bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock, 1667 Label*& trueTarget, FallThroughMode& fallThroughMode) 1668{ 1669 StatementNode* singleStatement = JSC::singleStatement(ifBlock); 1670 if (!singleStatement) 1671 return false; 1672 1673 if (singleStatement->isBreak()) { 1674 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement); 1675 Label* target = breakNode->trivialTarget(generator); 1676 if (!target) 1677 return false; 1678 trueTarget = target; 1679 fallThroughMode = FallThroughMeansFalse; 1680 return true; 1681 } 1682 1683 if (singleStatement->isContinue()) { 1684 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement); 1685 Label* target = continueNode->trivialTarget(generator); 1686 if (!target) 1687 return false; 1688 trueTarget = target; 1689 fallThroughMode = FallThroughMeansFalse; 1690 return true; 1691 } 1692 1693 return false; 1694} 1695 1696void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1697{ 1698 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1699 1700 RefPtr<Label> beforeThen = generator.newLabel(); 1701 RefPtr<Label> beforeElse = generator.newLabel(); 1702 RefPtr<Label> afterElse = generator.newLabel(); 1703 1704 Label* trueTarget = beforeThen.get(); 1705 Label* falseTarget = beforeElse.get(); 1706 FallThroughMode fallThroughMode = FallThroughMeansTrue; 1707 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode); 1708 1709 generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode); 1710 generator.emitLabel(beforeThen.get()); 1711 1712 if (!didFoldIfBlock) { 1713 generator.emitNode(dst, m_ifBlock); 1714 if (m_elseBlock) 1715 generator.emitJump(afterElse.get()); 1716 } 1717 1718 generator.emitLabel(beforeElse.get()); 1719 1720 if (m_elseBlock) 1721 generator.emitNode(dst, m_elseBlock); 1722 1723 generator.emitLabel(afterElse.get()); 1724} 1725 1726// ------------------------------ DoWhileNode ---------------------------------- 1727 1728void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1729{ 1730 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop); 1731 1732 RefPtr<Label> topOfLoop = generator.newLabel(); 1733 generator.emitLabel(topOfLoop.get()); 1734 generator.emitLoopHint(); 1735 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset()); 1736 1737 generator.emitNode(dst, m_statement); 1738 1739 generator.emitLabel(scope->continueTarget()); 1740 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset()); 1741 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse); 1742 1743 generator.emitLabel(scope->breakTarget()); 1744} 1745 1746// ------------------------------ WhileNode ------------------------------------ 1747 1748void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1749{ 1750 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop); 1751 RefPtr<Label> topOfLoop = generator.newLabel(); 1752 1753 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->startOffset(), m_expr->lineStartOffset()); 1754 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue); 1755 1756 generator.emitLabel(topOfLoop.get()); 1757 generator.emitLoopHint(); 1758 1759 generator.emitNode(dst, m_statement); 1760 1761 generator.emitLabel(scope->continueTarget()); 1762 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1763 1764 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse); 1765 1766 generator.emitLabel(scope->breakTarget()); 1767} 1768 1769// ------------------------------ ForNode -------------------------------------- 1770 1771void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1772{ 1773 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop); 1774 1775 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1776 1777 if (m_expr1) 1778 generator.emitNode(generator.ignoredResult(), m_expr1); 1779 1780 RefPtr<Label> topOfLoop = generator.newLabel(); 1781 if (m_expr2) 1782 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue); 1783 1784 generator.emitLabel(topOfLoop.get()); 1785 generator.emitLoopHint(); 1786 1787 generator.emitNode(dst, m_statement); 1788 1789 generator.emitLabel(scope->continueTarget()); 1790 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1791 if (m_expr3) 1792 generator.emitNode(generator.ignoredResult(), m_expr3); 1793 1794 if (m_expr2) 1795 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse); 1796 else 1797 generator.emitJump(topOfLoop.get()); 1798 1799 generator.emitLabel(scope->breakTarget()); 1800} 1801 1802// ------------------------------ ForInNode ------------------------------------ 1803 1804void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1805{ 1806 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop); 1807 1808 if (!m_lexpr->isAssignmentLocation()) { 1809 emitThrowReferenceError(generator, "Left side of for-in statement is not a reference."); 1810 return; 1811 } 1812 1813 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1814 1815 RefPtr<RegisterID> base = generator.newTemporary(); 1816 generator.emitNode(base.get(), m_expr); 1817 RefPtr<RegisterID> i = generator.newTemporary(); 1818 RefPtr<RegisterID> size = generator.newTemporary(); 1819 RefPtr<RegisterID> expectedSubscript; 1820 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget()); 1821 generator.emitJump(scope->continueTarget()); 1822 1823 RefPtr<Label> loopStart = generator.newLabel(); 1824 generator.emitLabel(loopStart.get()); 1825 generator.emitLoopHint(); 1826 1827 RegisterID* propertyName; 1828 bool optimizedForinAccess = false; 1829 if (m_lexpr->isResolveNode()) { 1830 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); 1831 Local local = generator.local(ident); 1832 if (!local.get()) { 1833 propertyName = generator.newTemporary(); 1834 RefPtr<RegisterID> protect = propertyName; 1835 if (generator.isStrictMode()) 1836 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1837 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident); 1838 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1839 generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 1840 } else { 1841 expectedSubscript = generator.newTemporary(); 1842 propertyName = expectedSubscript.get(); 1843 generator.emitMove(local.get(), propertyName); 1844 generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), local.get()); 1845 optimizedForinAccess = true; 1846 } 1847 } else if (m_lexpr->isDotAccessorNode()) { 1848 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr); 1849 const Identifier& ident = assignNode->identifier(); 1850 propertyName = generator.newTemporary(); 1851 RefPtr<RegisterID> protect = propertyName; 1852 RegisterID* base = generator.emitNode(assignNode->base()); 1853 1854 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd()); 1855 generator.emitPutById(base, ident, propertyName); 1856 } else if (m_lexpr->isBracketAccessorNode()) { 1857 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr); 1858 propertyName = generator.newTemporary(); 1859 RefPtr<RegisterID> protect = propertyName; 1860 RefPtr<RegisterID> base = generator.emitNode(assignNode->base()); 1861 RegisterID* subscript = generator.emitNode(assignNode->subscript()); 1862 1863 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd()); 1864 generator.emitPutByVal(base.get(), subscript, propertyName); 1865 } else { 1866 ASSERT(m_lexpr->isDeconstructionNode()); 1867 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr); 1868 auto binding = assignNode->bindings(); 1869 if (binding->isBindingNode()) { 1870 auto simpleBinding = static_cast<BindingNode*>(binding); 1871 Identifier ident = simpleBinding->boundProperty(); 1872 Local local = generator.local(ident); 1873 propertyName = local.get(); 1874 if (!propertyName || local.isCaptured()) 1875 goto genericBinding; 1876 expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName); 1877 generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName); 1878 optimizedForinAccess = true; 1879 goto completedSimpleBinding; 1880 } else { 1881 genericBinding: 1882 propertyName = generator.newTemporary(); 1883 RefPtr<RegisterID> protect(propertyName); 1884 assignNode->bindings()->bindValue(generator, propertyName); 1885 } 1886 completedSimpleBinding: 1887 ; 1888 } 1889 1890 generator.emitNode(dst, m_statement); 1891 1892 if (optimizedForinAccess) 1893 generator.popOptimisedForIn(); 1894 1895 generator.emitLabel(scope->continueTarget()); 1896 generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get()); 1897 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1898 generator.emitLabel(scope->breakTarget()); 1899} 1900 1901// ------------------------------ ForOfNode ------------------------------------ 1902void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1903{ 1904 if (!m_lexpr->isAssignmentLocation()) { 1905 emitThrowReferenceError(generator, "Left side of for-of statement is not a reference."); 1906 return; 1907 } 1908 1909 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop); 1910 1911 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1912 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value) 1913 { 1914 if (m_lexpr->isResolveNode()) { 1915 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); 1916 if (Local local = generator.local(ident)) 1917 generator.emitMove(local.get(), value); 1918 else { 1919 if (generator.isStrictMode()) 1920 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1921 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident); 1922 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1923 generator.emitPutToScope(scope, ident, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 1924 } 1925 } else if (m_lexpr->isDotAccessorNode()) { 1926 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr); 1927 const Identifier& ident = assignNode->identifier(); 1928 RefPtr<RegisterID> base = generator.emitNode(assignNode->base()); 1929 1930 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd()); 1931 generator.emitPutById(base.get(), ident, value); 1932 } else if (m_lexpr->isBracketAccessorNode()) { 1933 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr); 1934 RefPtr<RegisterID> base = generator.emitNode(assignNode->base()); 1935 RegisterID* subscript = generator.emitNode(assignNode->subscript()); 1936 1937 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd()); 1938 generator.emitPutByVal(base.get(), subscript, value); 1939 } else { 1940 ASSERT(m_lexpr->isDeconstructionNode()); 1941 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr); 1942 assignNode->bindings()->bindValue(generator, value); 1943 } 1944 generator.emitNode(dst, m_statement); 1945 }; 1946 generator.emitEnumeration(this, m_expr, extractor); 1947} 1948 1949// ------------------------------ ContinueNode --------------------------------- 1950 1951Label* ContinueNode::trivialTarget(BytecodeGenerator& generator) 1952{ 1953 if (generator.shouldEmitDebugHooks()) 1954 return 0; 1955 1956 LabelScopePtr scope = generator.continueTarget(m_ident); 1957 ASSERT(scope); 1958 1959 if (generator.scopeDepth() != scope->scopeDepth()) 1960 return 0; 1961 1962 return scope->continueTarget(); 1963} 1964 1965void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1966{ 1967 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1968 1969 LabelScopePtr scope = generator.continueTarget(m_ident); 1970 ASSERT(scope); 1971 1972 generator.emitPopScopes(scope->scopeDepth()); 1973 generator.emitJump(scope->continueTarget()); 1974} 1975 1976// ------------------------------ BreakNode ------------------------------------ 1977 1978Label* BreakNode::trivialTarget(BytecodeGenerator& generator) 1979{ 1980 if (generator.shouldEmitDebugHooks()) 1981 return 0; 1982 1983 LabelScopePtr scope = generator.breakTarget(m_ident); 1984 ASSERT(scope); 1985 1986 if (generator.scopeDepth() != scope->scopeDepth()) 1987 return 0; 1988 1989 return scope->breakTarget(); 1990} 1991 1992void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 1993{ 1994 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 1995 1996 LabelScopePtr scope = generator.breakTarget(m_ident); 1997 ASSERT(scope); 1998 1999 generator.emitPopScopes(scope->scopeDepth()); 2000 generator.emitJump(scope->breakTarget()); 2001} 2002 2003// ------------------------------ ReturnNode ----------------------------------- 2004 2005void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2006{ 2007 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 2008 ASSERT(generator.codeType() == FunctionCode); 2009 2010 if (dst == generator.ignoredResult()) 2011 dst = 0; 2012 2013 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined()); 2014 if (generator.scopeDepth()) { 2015 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get()); 2016 generator.emitPopScopes(0); 2017 } 2018 2019 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset()); 2020 generator.emitReturn(returnRegister.get()); 2021} 2022 2023// ------------------------------ WithNode ------------------------------------- 2024 2025void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2026{ 2027 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 2028 2029 RefPtr<RegisterID> scope = generator.emitNode(m_expr); 2030 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot); 2031 generator.emitPushWithScope(scope.get()); 2032 generator.emitNode(dst, m_statement); 2033 generator.emitPopScope(); 2034} 2035 2036// ------------------------------ CaseClauseNode -------------------------------- 2037 2038inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2039{ 2040 if (!m_statements) 2041 return; 2042 m_statements->emitBytecode(generator, dst); 2043} 2044 2045// ------------------------------ CaseBlockNode -------------------------------- 2046 2047enum SwitchKind { 2048 SwitchUnset = 0, 2049 SwitchNumber = 1, 2050 SwitchString = 2, 2051 SwitchNeither = 3 2052}; 2053 2054static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num) 2055{ 2056 for (; list; list = list->getNext()) { 2057 ExpressionNode* clauseExpression = list->getClause()->expr(); 2058 literalVector.append(clauseExpression); 2059 if (clauseExpression->isNumber()) { 2060 double value = static_cast<NumberNode*>(clauseExpression)->value(); 2061 int32_t intVal = static_cast<int32_t>(value); 2062 if ((typeForTable & ~SwitchNumber) || (intVal != value)) { 2063 typeForTable = SwitchNeither; 2064 break; 2065 } 2066 if (intVal < min_num) 2067 min_num = intVal; 2068 if (intVal > max_num) 2069 max_num = intVal; 2070 typeForTable = SwitchNumber; 2071 continue; 2072 } 2073 if (clauseExpression->isString()) { 2074 if (typeForTable & ~SwitchString) { 2075 typeForTable = SwitchNeither; 2076 break; 2077 } 2078 const String& value = static_cast<StringNode*>(clauseExpression)->value().string(); 2079 if (singleCharacterSwitch &= value.length() == 1) { 2080 int32_t intVal = value[0]; 2081 if (intVal < min_num) 2082 min_num = intVal; 2083 if (intVal > max_num) 2084 max_num = intVal; 2085 } 2086 typeForTable = SwitchString; 2087 continue; 2088 } 2089 typeForTable = SwitchNeither; 2090 break; 2091 } 2092} 2093 2094static inline size_t length(ClauseListNode* list1, ClauseListNode* list2) 2095{ 2096 size_t length = 0; 2097 for (ClauseListNode* node = list1; node; node = node->getNext()) 2098 ++length; 2099 for (ClauseListNode* node = list2; node; node = node->getNext()) 2100 ++length; 2101 return length; 2102} 2103 2104SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num) 2105{ 2106 if (length(m_list1, m_list2) < s_tableSwitchMinimum) 2107 return SwitchInfo::SwitchNone; 2108 2109 SwitchKind typeForTable = SwitchUnset; 2110 bool singleCharacterSwitch = true; 2111 2112 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); 2113 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); 2114 2115 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither) 2116 return SwitchInfo::SwitchNone; 2117 2118 if (typeForTable == SwitchNumber) { 2119 int32_t range = max_num - min_num; 2120 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10) 2121 return SwitchInfo::SwitchImmediate; 2122 return SwitchInfo::SwitchNone; 2123 } 2124 2125 ASSERT(typeForTable == SwitchString); 2126 2127 if (singleCharacterSwitch) { 2128 int32_t range = max_num - min_num; 2129 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10) 2130 return SwitchInfo::SwitchCharacter; 2131 } 2132 2133 return SwitchInfo::SwitchString; 2134} 2135 2136void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst) 2137{ 2138 RefPtr<Label> defaultLabel; 2139 Vector<RefPtr<Label>, 8> labelVector; 2140 Vector<ExpressionNode*, 8> literalVector; 2141 int32_t min_num = std::numeric_limits<int32_t>::max(); 2142 int32_t max_num = std::numeric_limits<int32_t>::min(); 2143 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num); 2144 2145 if (switchType != SwitchInfo::SwitchNone) { 2146 // Prepare the various labels 2147 for (uint32_t i = 0; i < literalVector.size(); i++) 2148 labelVector.append(generator.newLabel()); 2149 defaultLabel = generator.newLabel(); 2150 generator.beginSwitch(switchExpression, switchType); 2151 } else { 2152 // Setup jumps 2153 for (ClauseListNode* list = m_list1; list; list = list->getNext()) { 2154 RefPtr<RegisterID> clauseVal = generator.newTemporary(); 2155 generator.emitNode(clauseVal.get(), list->getClause()->expr()); 2156 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); 2157 labelVector.append(generator.newLabel()); 2158 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); 2159 } 2160 2161 for (ClauseListNode* list = m_list2; list; list = list->getNext()) { 2162 RefPtr<RegisterID> clauseVal = generator.newTemporary(); 2163 generator.emitNode(clauseVal.get(), list->getClause()->expr()); 2164 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); 2165 labelVector.append(generator.newLabel()); 2166 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); 2167 } 2168 defaultLabel = generator.newLabel(); 2169 generator.emitJump(defaultLabel.get()); 2170 } 2171 2172 size_t i = 0; 2173 for (ClauseListNode* list = m_list1; list; list = list->getNext()) { 2174 generator.emitLabel(labelVector[i++].get()); 2175 list->getClause()->emitBytecode(generator, dst); 2176 } 2177 2178 if (m_defaultClause) { 2179 generator.emitLabel(defaultLabel.get()); 2180 m_defaultClause->emitBytecode(generator, dst); 2181 } 2182 2183 for (ClauseListNode* list = m_list2; list; list = list->getNext()) { 2184 generator.emitLabel(labelVector[i++].get()); 2185 list->getClause()->emitBytecode(generator, dst); 2186 } 2187 if (!m_defaultClause) 2188 generator.emitLabel(defaultLabel.get()); 2189 2190 ASSERT(i == labelVector.size()); 2191 if (switchType != SwitchInfo::SwitchNone) { 2192 ASSERT(labelVector.size() == literalVector.size()); 2193 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num); 2194 } 2195} 2196 2197// ------------------------------ SwitchNode ----------------------------------- 2198 2199void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2200{ 2201 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 2202 2203 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch); 2204 2205 RefPtr<RegisterID> r0 = generator.emitNode(m_expr); 2206 m_block->emitBytecodeForBlock(generator, r0.get(), dst); 2207 2208 generator.emitLabel(scope->breakTarget()); 2209} 2210 2211// ------------------------------ LabelNode ------------------------------------ 2212 2213void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2214{ 2215 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 2216 2217 ASSERT(!generator.breakTarget(m_name)); 2218 2219 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name); 2220 generator.emitNode(dst, m_statement); 2221 2222 generator.emitLabel(scope->breakTarget()); 2223} 2224 2225// ------------------------------ ThrowNode ------------------------------------ 2226 2227void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2228{ 2229 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 2230 2231 if (dst == generator.ignoredResult()) 2232 dst = 0; 2233 RefPtr<RegisterID> expr = generator.emitNode(m_expr); 2234 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 2235 generator.emitThrow(expr.get()); 2236} 2237 2238// ------------------------------ TryNode -------------------------------------- 2239 2240void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2241{ 2242 // NOTE: The catch and finally blocks must be labeled explicitly, so the 2243 // optimizer knows they may be jumped to from anywhere. 2244 2245 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); 2246 2247 ASSERT(m_catchBlock || m_finallyBlock); 2248 2249 RefPtr<Label> tryStartLabel = generator.newLabel(); 2250 generator.emitLabel(tryStartLabel.get()); 2251 2252 if (m_finallyBlock) 2253 generator.pushFinallyContext(m_finallyBlock); 2254 TryData* tryData = generator.pushTry(tryStartLabel.get()); 2255 2256 generator.emitNode(dst, m_tryBlock); 2257 2258 if (m_catchBlock) { 2259 RefPtr<Label> catchEndLabel = generator.newLabel(); 2260 2261 // Normal path: jump over the catch block. 2262 generator.emitJump(catchEndLabel.get()); 2263 2264 // Uncaught exception path: the catch block. 2265 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); 2266 RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get()); 2267 2268 if (m_finallyBlock) { 2269 // If the catch block throws an exception and we have a finally block, then the finally 2270 // block should "catch" that exception. 2271 tryData = generator.pushTry(here.get()); 2272 } 2273 2274 generator.emitPushCatchScope(m_exceptionIdent, exceptionRegister.get(), DontDelete); 2275 generator.emitNode(dst, m_catchBlock); 2276 generator.emitPopScope(); 2277 generator.emitLabel(catchEndLabel.get()); 2278 } 2279 2280 if (m_finallyBlock) { 2281 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get()); 2282 2283 generator.popFinallyContext(); 2284 2285 RefPtr<Label> finallyEndLabel = generator.newLabel(); 2286 2287 // Normal path: run the finally code, and jump to the end. 2288 generator.emitNode(dst, m_finallyBlock); 2289 generator.emitJump(finallyEndLabel.get()); 2290 2291 // Uncaught exception path: invoke the finally block, then re-throw the exception. 2292 RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get()); 2293 generator.emitNode(dst, m_finallyBlock); 2294 generator.emitThrow(tempExceptionRegister.get()); 2295 2296 generator.emitLabel(finallyEndLabel.get()); 2297 } 2298} 2299 2300// ------------------------------ ScopeNode ----------------------------- 2301 2302inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst) 2303{ 2304 if (!m_statements) 2305 return; 2306 m_statements->emitBytecode(generator, dst); 2307} 2308 2309// ------------------------------ ProgramNode ----------------------------- 2310 2311void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 2312{ 2313 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset()); 2314 2315 RefPtr<RegisterID> dstRegister = generator.newTemporary(); 2316 generator.emitLoad(dstRegister.get(), jsUndefined()); 2317 emitStatementsBytecode(generator, dstRegister.get()); 2318 2319 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset()); 2320 generator.emitEnd(dstRegister.get()); 2321} 2322 2323// ------------------------------ EvalNode ----------------------------- 2324 2325void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 2326{ 2327 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset()); 2328 2329 RefPtr<RegisterID> dstRegister = generator.newTemporary(); 2330 generator.emitLoad(dstRegister.get(), jsUndefined()); 2331 emitStatementsBytecode(generator, dstRegister.get()); 2332 2333 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset()); 2334 generator.emitEnd(dstRegister.get()); 2335} 2336 2337// ------------------------------ FunctionBodyNode ----------------------------- 2338 2339void FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 2340{ 2341 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset()); 2342 emitStatementsBytecode(generator, generator.ignoredResult()); 2343 2344 StatementNode* singleStatement = this->singleStatement(); 2345 ReturnNode* returnNode = 0; 2346 2347 // Check for a return statement at the end of a function composed of a single block. 2348 if (singleStatement && singleStatement->isBlock()) { 2349 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement(); 2350 if (lastStatementInBlock && lastStatementInBlock->isReturnNode()) 2351 returnNode = static_cast<ReturnNode*>(lastStatementInBlock); 2352 } 2353 2354 // If there is no return we must automatically insert one. 2355 if (!returnNode) { 2356 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined()); 2357 ASSERT(startOffset() >= lineStartOffset()); 2358 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset()); 2359 generator.emitReturn(r0); 2360 return; 2361 } 2362 2363 // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare. 2364 if (static_cast<BlockNode*>(singleStatement)->singleStatement()) { 2365 ExpressionNode* returnValueExpression = returnNode->value(); 2366 if (returnValueExpression && returnValueExpression->isSubtract()) { 2367 ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs(); 2368 ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs(); 2369 if (lhsExpression->isResolveNode() 2370 && rhsExpression->isResolveNode() 2371 && generator.isArgumentNumber(static_cast<ResolveNode*>(lhsExpression)->identifier(), 0) 2372 && generator.isArgumentNumber(static_cast<ResolveNode*>(rhsExpression)->identifier(), 1)) { 2373 2374 generator.setIsNumericCompareFunction(true); 2375 } 2376 } 2377 } 2378} 2379 2380// ------------------------------ FuncDeclNode --------------------------------- 2381 2382void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*) 2383{ 2384} 2385 2386// ------------------------------ FuncExprNode --------------------------------- 2387 2388RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2389{ 2390 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this); 2391} 2392 2393// ------------------------------ DeconstructingAssignmentNode ----------------- 2394RegisterID* DeconstructingAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 2395{ 2396 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer)) 2397 return result; 2398 RefPtr<RegisterID> initializer = generator.tempDestination(dst); 2399 generator.emitNode(initializer.get(), m_initializer); 2400 m_bindings->bindValue(generator, initializer.get()); 2401 return generator.moveToDestinationIfNeeded(dst, initializer.get()); 2402} 2403 2404DeconstructionPatternNode::~DeconstructionPatternNode() 2405{ 2406} 2407 2408void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const 2409{ 2410 for (size_t i = 0; i < m_targetPatterns.size(); i++) { 2411 auto target = m_targetPatterns[i]; 2412 if (!target) 2413 continue; 2414 RefPtr<RegisterID> temp = generator.newTemporary(); 2415 generator.emitLoad(temp.get(), jsNumber(i)); 2416 generator.emitGetByVal(temp.get(), rhs, temp.get()); 2417 target->bindValue(generator, temp.get()); 2418 } 2419} 2420 2421RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs) 2422{ 2423 if (rhs->isResolveNode() 2424 && generator.willResolveToArguments(static_cast<ResolveNode*>(rhs)->identifier()) 2425 && !generator.symbolTable().slowArguments()) { 2426 for (size_t i = 0; i < m_targetPatterns.size(); i++) { 2427 auto target = m_targetPatterns[i]; 2428 if (!target) 2429 continue; 2430 2431 RefPtr<RegisterID> temp = generator.newTemporary(); 2432 generator.emitLoad(temp.get(), jsNumber(i)); 2433 generator.emitGetArgumentByVal(temp.get(), generator.uncheckedRegisterForArguments(), temp.get()); 2434 target->bindValue(generator, temp.get()); 2435 } 2436 if (dst == generator.ignoredResult() || !dst) 2437 return generator.emitLoad(generator.finalDestination(dst), jsUndefined()); 2438 Local local = generator.local(generator.vm()->propertyNames->arguments); 2439 return generator.moveToDestinationIfNeeded(dst, local.get()); 2440 } 2441 if (!rhs->isSimpleArray()) 2442 return 0; 2443 2444 RefPtr<RegisterID> resultRegister; 2445 if (dst && dst != generator.ignoredResult()) 2446 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0); 2447 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements(); 2448 Vector<ExpressionNode*> elements; 2449 for (; elementNodes; elementNodes = elementNodes->next()) 2450 elements.append(elementNodes->value()); 2451 if (m_targetPatterns.size() != elements.size()) 2452 return 0; 2453 Vector<RefPtr<RegisterID>> registers; 2454 registers.reserveCapacity(m_targetPatterns.size()); 2455 for (size_t i = 0; i < m_targetPatterns.size(); i++) { 2456 registers.uncheckedAppend(generator.newTemporary()); 2457 generator.emitNode(registers.last().get(), elements[i]); 2458 if (resultRegister) 2459 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get()); 2460 } 2461 2462 for (size_t i = 0; i < m_targetPatterns.size(); i++) { 2463 if (m_targetPatterns[i]) 2464 m_targetPatterns[i]->bindValue(generator, registers[i].get()); 2465 } 2466 if (resultRegister) 2467 return generator.moveToDestinationIfNeeded(dst, resultRegister.get()); 2468 return generator.emitLoad(generator.finalDestination(dst), jsUndefined()); 2469} 2470 2471void ArrayPatternNode::toString(StringBuilder& builder) const 2472{ 2473 builder.append('['); 2474 for (size_t i = 0; i < m_targetPatterns.size(); i++) { 2475 if (!m_targetPatterns[i]) { 2476 builder.append(','); 2477 continue; 2478 } 2479 m_targetPatterns[i]->toString(builder); 2480 if (i < m_targetPatterns.size() - 1) 2481 builder.append(','); 2482 } 2483 builder.append(']'); 2484} 2485 2486void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const 2487{ 2488 for (size_t i = 0; i < m_targetPatterns.size(); i++) { 2489 if (DeconstructionPatternNode* node = m_targetPatterns[i].get()) 2490 node->collectBoundIdentifiers(identifiers); 2491 } 2492} 2493 2494void ObjectPatternNode::toString(StringBuilder& builder) const 2495{ 2496 builder.append('{'); 2497 for (size_t i = 0; i < m_targetPatterns.size(); i++) { 2498 if (m_targetPatterns[i].wasString) { 2499 builder.append('"'); 2500 escapeStringToBuilder(builder, m_targetPatterns[i].propertyName.string()); 2501 builder.append('"'); 2502 } else 2503 builder.append(m_targetPatterns[i].propertyName.string()); 2504 builder.append(":"); 2505 m_targetPatterns[i].pattern->toString(builder); 2506 if (i < m_targetPatterns.size() - 1) 2507 builder.append(','); 2508 } 2509 builder.append('}'); 2510} 2511 2512void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const 2513{ 2514 for (size_t i = 0; i < m_targetPatterns.size(); i++) { 2515 auto& target = m_targetPatterns[i]; 2516 RefPtr<RegisterID> temp = generator.newTemporary(); 2517 generator.emitGetById(temp.get(), rhs, target.propertyName); 2518 target.pattern->bindValue(generator, temp.get()); 2519 } 2520} 2521 2522void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const 2523{ 2524 for (size_t i = 0; i < m_targetPatterns.size(); i++) 2525 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers); 2526} 2527 2528void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const 2529{ 2530 if (Local local = generator.local(m_boundProperty)) { 2531 if (local.isReadOnly()) { 2532 generator.emitReadOnlyExceptionIfNeeded(); 2533 return; 2534 } 2535 generator.emitMove(local.get(), value); 2536 return; 2537 } 2538 if (generator.isStrictMode()) 2539 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd()); 2540 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), m_boundProperty); 2541 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd()); 2542 generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 2543 return; 2544} 2545 2546void BindingNode::toString(StringBuilder& builder) const 2547{ 2548 builder.append(m_boundProperty.string()); 2549} 2550 2551void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const 2552{ 2553 identifiers.append(m_boundProperty); 2554} 2555 2556RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*) 2557{ 2558 RELEASE_ASSERT_NOT_REACHED(); 2559 return 0; 2560} 2561 2562} // namespace JSC 2563