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