Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: src/x64/full-codegen-x64.cc

Issue 6031014: Add deoptimization support to full-codegen-x64.cc (insert PrepareForBailout i... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 452
453 453
454 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { 454 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
455 Heap::RootListIndex value_root_index = 455 Heap::RootListIndex value_root_index =
456 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 456 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
457 __ PushRoot(value_root_index); 457 __ PushRoot(value_root_index);
458 } 458 }
459 459
460 460
461 void FullCodeGenerator::TestContext::Plug(bool flag) const { 461 void FullCodeGenerator::TestContext::Plug(bool flag) const {
462 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 462 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, true, NULL, NULL);
463 if (flag) { 463 if (flag) {
464 if (true_label_ != fall_through_) __ jmp(true_label_); 464 if (true_label_ != fall_through_) __ jmp(true_label_);
465 } else { 465 } else {
466 if (false_label_ != fall_through_) __ jmp(false_label_); 466 if (false_label_ != fall_through_) __ jmp(false_label_);
467 } 467 }
468 } 468 }
469 469
470 470
471 void FullCodeGenerator::DoTest(Label* if_true, 471 void FullCodeGenerator::DoTest(Label* if_true,
472 Label* if_false, 472 Label* if_false,
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 548 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
549 __ RecordWrite(scratch1, offset, src, scratch2); 549 __ RecordWrite(scratch1, offset, src, scratch2);
550 } 550 }
551 } 551 }
552 552
553 553
554 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, 554 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
555 bool should_normalize, 555 bool should_normalize,
556 Label* if_true, 556 Label* if_true,
557 Label* if_false) { 557 Label* if_false) {
558 // Only prepare for bailouts before splits if we're in a test
559 // context. Otherwise, we let the Visit function deal with the
560 // preparation to avoid preparing with the same AST id twice.
561 if (!context()->IsTest() || !info_->IsOptimizable()) return;
562
563 NearLabel skip;
564 if (should_normalize) __ jmp(&skip);
565
566 ForwardBailoutStack* current = forward_bailout_stack_;
567 while (current != NULL) {
568 PrepareForBailout(current->expr(), state);
569 current = current->parent();
570 }
571
572 if (should_normalize) {
573 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
574 Split(equal, if_true, if_false, NULL);
575 __ bind(&skip);
576 }
558 } 577 }
559 578
560 579
561 void FullCodeGenerator::EmitDeclaration(Variable* variable, 580 void FullCodeGenerator::EmitDeclaration(Variable* variable,
562 Variable::Mode mode, 581 Variable::Mode mode,
563 FunctionLiteral* function) { 582 FunctionLiteral* function) {
564 Comment cmnt(masm_, "[ Declaration"); 583 Comment cmnt(masm_, "[ Declaration");
565 ASSERT(variable != NULL); // Must have been resolved. 584 ASSERT(variable != NULL); // Must have been resolved.
566 Slot* slot = variable->AsSlot(); 585 Slot* slot = variable->AsSlot();
567 Property* prop = variable->AsProperty(); 586 Property* prop = variable->AsProperty();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 __ Push(Smi::FromInt(is_eval() ? 1 : 0)); 681 __ Push(Smi::FromInt(is_eval() ? 1 : 0));
663 __ CallRuntime(Runtime::kDeclareGlobals, 3); 682 __ CallRuntime(Runtime::kDeclareGlobals, 3);
664 // Return value is ignored. 683 // Return value is ignored.
665 } 684 }
666 685
667 686
668 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 687 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
669 Comment cmnt(masm_, "[ SwitchStatement"); 688 Comment cmnt(masm_, "[ SwitchStatement");
670 Breakable nested_statement(this, stmt); 689 Breakable nested_statement(this, stmt);
671 SetStatementPosition(stmt); 690 SetStatementPosition(stmt);
691
672 // Keep the switch value on the stack until a case matches. 692 // Keep the switch value on the stack until a case matches.
673 VisitForStackValue(stmt->tag()); 693 VisitForStackValue(stmt->tag());
694 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
674 695
675 ZoneList<CaseClause*>* clauses = stmt->cases(); 696 ZoneList<CaseClause*>* clauses = stmt->cases();
676 CaseClause* default_clause = NULL; // Can occur anywhere in the list. 697 CaseClause* default_clause = NULL; // Can occur anywhere in the list.
677 698
678 Label next_test; // Recycled for each test. 699 Label next_test; // Recycled for each test.
679 // Compile all the tests with branches to their bodies. 700 // Compile all the tests with branches to their bodies.
680 for (int i = 0; i < clauses->length(); i++) { 701 for (int i = 0; i < clauses->length(); i++) {
681 CaseClause* clause = clauses->at(i); 702 CaseClause* clause = clauses->at(i);
682 // The default is not a test, but remember it as final fall through. 703 // The default is not a test, but remember it as final fall through.
683 if (clause->is_default()) { 704 if (clause->is_default()) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 749
729 // Compile all the case bodies. 750 // Compile all the case bodies.
730 for (int i = 0; i < clauses->length(); i++) { 751 for (int i = 0; i < clauses->length(); i++) {
731 Comment cmnt(masm_, "[ Case body"); 752 Comment cmnt(masm_, "[ Case body");
732 CaseClause* clause = clauses->at(i); 753 CaseClause* clause = clauses->at(i);
733 __ bind(clause->body_target()->entry_label()); 754 __ bind(clause->body_target()->entry_label());
734 VisitStatements(clause->statements()); 755 VisitStatements(clause->statements());
735 } 756 }
736 757
737 __ bind(nested_statement.break_target()); 758 __ bind(nested_statement.break_target());
759 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
738 } 760 }
739 761
740 762
741 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 763 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
742 Comment cmnt(masm_, "[ ForInStatement"); 764 Comment cmnt(masm_, "[ ForInStatement");
743 SetStatementPosition(stmt); 765 SetStatementPosition(stmt);
744 766
745 Label loop, exit; 767 Label loop, exit;
746 ForIn loop_statement(this, stmt); 768 ForIn loop_statement(this, stmt);
747 increment_loop_depth(); 769 increment_loop_depth();
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
1217 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1239 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1218 // Fall through. 1240 // Fall through.
1219 case ObjectLiteral::Property::COMPUTED: 1241 case ObjectLiteral::Property::COMPUTED:
1220 if (key->handle()->IsSymbol()) { 1242 if (key->handle()->IsSymbol()) {
1221 VisitForAccumulatorValue(value); 1243 VisitForAccumulatorValue(value);
1222 __ Move(rcx, key->handle()); 1244 __ Move(rcx, key->handle());
1223 __ movq(rdx, Operand(rsp, 0)); 1245 __ movq(rdx, Operand(rsp, 0));
1224 if (property->emit_store()) { 1246 if (property->emit_store()) {
1225 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1247 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1226 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1248 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1249 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1227 } 1250 }
1228 break; 1251 break;
1229 } 1252 }
1230 // Fall through. 1253 // Fall through.
1231 case ObjectLiteral::Property::PROTOTYPE: 1254 case ObjectLiteral::Property::PROTOTYPE:
1232 __ push(Operand(rsp, 0)); // Duplicate receiver. 1255 __ push(Operand(rsp, 0)); // Duplicate receiver.
1233 VisitForStackValue(key); 1256 VisitForStackValue(key);
1234 VisitForStackValue(value); 1257 VisitForStackValue(value);
1235 if (property->emit_store()) { 1258 if (property->emit_store()) {
1236 __ CallRuntime(Runtime::kSetProperty, 3); 1259 __ CallRuntime(Runtime::kSetProperty, 3);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 VisitForAccumulatorValue(subexpr); 1327 VisitForAccumulatorValue(subexpr);
1305 1328
1306 // Store the subexpression value in the array's elements. 1329 // Store the subexpression value in the array's elements.
1307 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 1330 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal.
1308 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 1331 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
1309 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1332 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1310 __ movq(FieldOperand(rbx, offset), result_register()); 1333 __ movq(FieldOperand(rbx, offset), result_register());
1311 1334
1312 // Update the write barrier for the array store. 1335 // Update the write barrier for the array store.
1313 __ RecordWrite(rbx, offset, result_register(), rcx); 1336 __ RecordWrite(rbx, offset, result_register(), rcx);
1337
1338 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1314 } 1339 }
1315 1340
1316 if (result_saved) { 1341 if (result_saved) {
1317 context()->PlugTOS(); 1342 context()->PlugTOS();
1318 } else { 1343 } else {
1319 context()->Plug(rax); 1344 context()->Plug(rax);
1320 } 1345 }
1321 } 1346 }
1322 1347
1323 1348
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 break; 1401 break;
1377 case NAMED_PROPERTY: 1402 case NAMED_PROPERTY:
1378 EmitNamedPropertyLoad(property); 1403 EmitNamedPropertyLoad(property);
1379 break; 1404 break;
1380 case KEYED_PROPERTY: 1405 case KEYED_PROPERTY:
1381 EmitKeyedPropertyLoad(property); 1406 EmitKeyedPropertyLoad(property);
1382 break; 1407 break;
1383 } 1408 }
1384 } 1409 }
1385 1410
1411 // For property compound assignments we need another deoptimization
1412 // point after the property load.
1413 if (property != NULL) {
1414 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
1415 }
1416
1386 Token::Value op = expr->binary_op(); 1417 Token::Value op = expr->binary_op();
1387 ConstantOperand constant = ShouldInlineSmiCase(op) 1418 ConstantOperand constant = ShouldInlineSmiCase(op)
1388 ? GetConstantOperand(op, expr->target(), expr->value()) 1419 ? GetConstantOperand(op, expr->target(), expr->value())
1389 : kNoConstants; 1420 : kNoConstants;
1390 ASSERT(constant == kRightConstant || constant == kNoConstants); 1421 ASSERT(constant == kRightConstant || constant == kNoConstants);
1391 if (constant == kNoConstants) { 1422 if (constant == kNoConstants) {
1392 __ push(rax); // Left operand goes on the stack. 1423 __ push(rax); // Left operand goes on the stack.
1393 VisitForAccumulatorValue(expr->value()); 1424 VisitForAccumulatorValue(expr->value());
1394 } 1425 }
1395 1426
1396 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 1427 OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1397 ? OVERWRITE_RIGHT 1428 ? OVERWRITE_RIGHT
1398 : NO_OVERWRITE; 1429 : NO_OVERWRITE;
1399 SetSourcePosition(expr->position() + 1); 1430 SetSourcePosition(expr->position() + 1);
1400 AccumulatorValueContext context(this); 1431 AccumulatorValueContext context(this);
1401 if (ShouldInlineSmiCase(op)) { 1432 if (ShouldInlineSmiCase(op)) {
1402 EmitInlineSmiBinaryOp(expr, 1433 EmitInlineSmiBinaryOp(expr,
1403 op, 1434 op,
1404 mode, 1435 mode,
1405 expr->target(), 1436 expr->target(),
1406 expr->value(), 1437 expr->value(),
1407 constant); 1438 constant);
1408 } else { 1439 } else {
1409 EmitBinaryOp(op, mode); 1440 EmitBinaryOp(op, mode);
1410 } 1441 }
1442 // Deoptimization point in case the binary operation may have side effects.
1443 PrepareForBailout(expr->binary_operation(), TOS_REG);
1411 } else { 1444 } else {
1412 VisitForAccumulatorValue(expr->value()); 1445 VisitForAccumulatorValue(expr->value());
1413 } 1446 }
1414 1447
1415 // Record source position before possible IC call. 1448 // Record source position before possible IC call.
1416 SetSourcePosition(expr->position()); 1449 SetSourcePosition(expr->position());
1417 1450
1418 // Store the value. 1451 // Store the value.
1419 switch (assign_type) { 1452 switch (assign_type) {
1420 case VARIABLE: 1453 case VARIABLE:
1421 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1454 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1422 expr->op()); 1455 expr->op());
1456 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1423 context()->Plug(rax); 1457 context()->Plug(rax);
1424 break; 1458 break;
1425 case NAMED_PROPERTY: 1459 case NAMED_PROPERTY:
1426 EmitNamedPropertyAssignment(expr); 1460 EmitNamedPropertyAssignment(expr);
1427 break; 1461 break;
1428 case KEYED_PROPERTY: 1462 case KEYED_PROPERTY:
1429 EmitKeyedPropertyAssignment(expr); 1463 EmitKeyedPropertyAssignment(expr);
1430 break; 1464 break;
1431 } 1465 }
1432 } 1466 }
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1522 __ pop(rdx); 1556 __ pop(rdx);
1523 stub.GenerateCall(masm_, rdx, rax); 1557 stub.GenerateCall(masm_, rdx, rax);
1524 } else { 1558 } else {
1525 __ push(result_register()); 1559 __ push(result_register());
1526 __ CallStub(&stub); 1560 __ CallStub(&stub);
1527 } 1561 }
1528 context()->Plug(rax); 1562 context()->Plug(rax);
1529 } 1563 }
1530 1564
1531 1565
1532 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_id) { 1566 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1533 // Invalid left-hand sides are rewritten to have a 'throw 1567 // Invalid left-hand sides are rewritten to have a 'throw
1534 // ReferenceError' on the left-hand side. 1568 // ReferenceError' on the left-hand side.
1535 if (!expr->IsValidLeftHandSide()) { 1569 if (!expr->IsValidLeftHandSide()) {
1536 VisitForEffect(expr); 1570 VisitForEffect(expr);
1537 return; 1571 return;
1538 } 1572 }
1539 1573
1540 // Left-hand side can only be a property, a global or a (parameter or local) 1574 // Left-hand side can only be a property, a global or a (parameter or local)
1541 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1575 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1542 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1576 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
(...skipping 27 matching lines...) Expand all
1570 VisitForStackValue(prop->obj()); 1604 VisitForStackValue(prop->obj());
1571 VisitForAccumulatorValue(prop->key()); 1605 VisitForAccumulatorValue(prop->key());
1572 __ movq(rcx, rax); 1606 __ movq(rcx, rax);
1573 __ pop(rdx); 1607 __ pop(rdx);
1574 __ pop(rax); 1608 __ pop(rax);
1575 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1609 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1576 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1610 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1577 break; 1611 break;
1578 } 1612 }
1579 } 1613 }
1614 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1580 context()->Plug(rax); 1615 context()->Plug(rax);
1581 } 1616 }
1582 1617
1583 1618
1584 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1619 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1585 Token::Value op) { 1620 Token::Value op) {
1586 // Left-hand sides that rewrite to explicit property accesses do not reach 1621 // Left-hand sides that rewrite to explicit property accesses do not reach
1587 // here. 1622 // here.
1588 ASSERT(var != NULL); 1623 ASSERT(var != NULL);
1589 ASSERT(var->is_global() || var->AsSlot() != NULL); 1624 ASSERT(var->is_global() || var->AsSlot() != NULL);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1681 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1716 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1682 1717
1683 // If the assignment ends an initialization block, revert to fast case. 1718 // If the assignment ends an initialization block, revert to fast case.
1684 if (expr->ends_initialization_block()) { 1719 if (expr->ends_initialization_block()) {
1685 __ push(rax); // Result of assignment, saved even if not needed. 1720 __ push(rax); // Result of assignment, saved even if not needed.
1686 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1721 __ push(Operand(rsp, kPointerSize)); // Receiver is under value.
1687 __ CallRuntime(Runtime::kToFastProperties, 1); 1722 __ CallRuntime(Runtime::kToFastProperties, 1);
1688 __ pop(rax); 1723 __ pop(rax);
1689 __ Drop(1); 1724 __ Drop(1);
1690 } 1725 }
1726 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1691 context()->Plug(rax); 1727 context()->Plug(rax);
1692 } 1728 }
1693 1729
1694 1730
1695 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1731 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1696 // Assignment to a property, using a keyed store IC. 1732 // Assignment to a property, using a keyed store IC.
1697 1733
1698 // If the assignment starts a block of assignments to the same object, 1734 // If the assignment starts a block of assignments to the same object,
1699 // change to slow case to avoid the quadratic behavior of repeatedly 1735 // change to slow case to avoid the quadratic behavior of repeatedly
1700 // adding fast properties. 1736 // adding fast properties.
(...skipping 18 matching lines...) Expand all
1719 1755
1720 // If the assignment ends an initialization block, revert to fast case. 1756 // If the assignment ends an initialization block, revert to fast case.
1721 if (expr->ends_initialization_block()) { 1757 if (expr->ends_initialization_block()) {
1722 __ pop(rdx); 1758 __ pop(rdx);
1723 __ push(rax); // Result of assignment, saved even if not needed. 1759 __ push(rax); // Result of assignment, saved even if not needed.
1724 __ push(rdx); 1760 __ push(rdx);
1725 __ CallRuntime(Runtime::kToFastProperties, 1); 1761 __ CallRuntime(Runtime::kToFastProperties, 1);
1726 __ pop(rax); 1762 __ pop(rax);
1727 } 1763 }
1728 1764
1765 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1729 context()->Plug(rax); 1766 context()->Plug(rax);
1730 } 1767 }
1731 1768
1732 1769
1733 void FullCodeGenerator::VisitProperty(Property* expr) { 1770 void FullCodeGenerator::VisitProperty(Property* expr) {
1734 Comment cmnt(masm_, "[ Property"); 1771 Comment cmnt(masm_, "[ Property");
1735 Expression* key = expr->key(); 1772 Expression* key = expr->key();
1736 1773
1737 if (key->IsPropertyName()) { 1774 if (key->IsPropertyName()) {
1738 VisitForAccumulatorValue(expr->obj()); 1775 VisitForAccumulatorValue(expr->obj());
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
2016 2053
2017 VisitForAccumulatorValue(args->at(0)); 2054 VisitForAccumulatorValue(args->at(0));
2018 2055
2019 Label materialize_true, materialize_false; 2056 Label materialize_true, materialize_false;
2020 Label* if_true = NULL; 2057 Label* if_true = NULL;
2021 Label* if_false = NULL; 2058 Label* if_false = NULL;
2022 Label* fall_through = NULL; 2059 Label* fall_through = NULL;
2023 context()->PrepareTest(&materialize_true, &materialize_false, 2060 context()->PrepareTest(&materialize_true, &materialize_false,
2024 &if_true, &if_false, &fall_through); 2061 &if_true, &if_false, &fall_through);
2025 2062
2063 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2026 __ JumpIfSmi(rax, if_true); 2064 __ JumpIfSmi(rax, if_true);
2027 __ jmp(if_false); 2065 __ jmp(if_false);
2028 2066
2029 context()->Plug(if_true, if_false); 2067 context()->Plug(if_true, if_false);
2030 } 2068 }
2031 2069
2032 2070
2033 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 2071 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
2034 ASSERT(args->length() == 1); 2072 ASSERT(args->length() == 1);
2035 2073
2036 VisitForAccumulatorValue(args->at(0)); 2074 VisitForAccumulatorValue(args->at(0));
2037 2075
2038 Label materialize_true, materialize_false; 2076 Label materialize_true, materialize_false;
2039 Label* if_true = NULL; 2077 Label* if_true = NULL;
2040 Label* if_false = NULL; 2078 Label* if_false = NULL;
2041 Label* fall_through = NULL; 2079 Label* fall_through = NULL;
2042 context()->PrepareTest(&materialize_true, &materialize_false, 2080 context()->PrepareTest(&materialize_true, &materialize_false,
2043 &if_true, &if_false, &fall_through); 2081 &if_true, &if_false, &fall_through);
2044 2082
2083 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2045 Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax); 2084 Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
2046 Split(non_negative_smi, if_true, if_false, fall_through); 2085 Split(non_negative_smi, if_true, if_false, fall_through);
2047 2086
2048 context()->Plug(if_true, if_false); 2087 context()->Plug(if_true, if_false);
2049 } 2088 }
2050 2089
2051 2090
2052 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 2091 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
2053 ASSERT(args->length() == 1); 2092 ASSERT(args->length() == 1);
2054 2093
(...skipping 11 matching lines...) Expand all
2066 __ j(equal, if_true); 2105 __ j(equal, if_true);
2067 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2106 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2068 // Undetectable objects behave like undefined when tested with typeof. 2107 // Undetectable objects behave like undefined when tested with typeof.
2069 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2108 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2070 Immediate(1 << Map::kIsUndetectable)); 2109 Immediate(1 << Map::kIsUndetectable));
2071 __ j(not_zero, if_false); 2110 __ j(not_zero, if_false);
2072 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2111 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2073 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); 2112 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE));
2074 __ j(below, if_false); 2113 __ j(below, if_false);
2075 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); 2114 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE));
2115 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2076 Split(below_equal, if_true, if_false, fall_through); 2116 Split(below_equal, if_true, if_false, fall_through);
2077 2117
2078 context()->Plug(if_true, if_false); 2118 context()->Plug(if_true, if_false);
2079 } 2119 }
2080 2120
2081 2121
2082 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 2122 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
2083 ASSERT(args->length() == 1); 2123 ASSERT(args->length() == 1);
2084 2124
2085 VisitForAccumulatorValue(args->at(0)); 2125 VisitForAccumulatorValue(args->at(0));
2086 2126
2087 Label materialize_true, materialize_false; 2127 Label materialize_true, materialize_false;
2088 Label* if_true = NULL; 2128 Label* if_true = NULL;
2089 Label* if_false = NULL; 2129 Label* if_false = NULL;
2090 Label* fall_through = NULL; 2130 Label* fall_through = NULL;
2091 context()->PrepareTest(&materialize_true, &materialize_false, 2131 context()->PrepareTest(&materialize_true, &materialize_false,
2092 &if_true, &if_false, &fall_through); 2132 &if_true, &if_false, &fall_through);
2093 2133
2094 __ JumpIfSmi(rax, if_false); 2134 __ JumpIfSmi(rax, if_false);
2095 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); 2135 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
2136 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2096 Split(above_equal, if_true, if_false, fall_through); 2137 Split(above_equal, if_true, if_false, fall_through);
2097 2138
2098 context()->Plug(if_true, if_false); 2139 context()->Plug(if_true, if_false);
2099 } 2140 }
2100 2141
2101 2142
2102 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2143 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2103 ASSERT(args->length() == 1); 2144 ASSERT(args->length() == 1);
2104 2145
2105 VisitForAccumulatorValue(args->at(0)); 2146 VisitForAccumulatorValue(args->at(0));
2106 2147
2107 Label materialize_true, materialize_false; 2148 Label materialize_true, materialize_false;
2108 Label* if_true = NULL; 2149 Label* if_true = NULL;
2109 Label* if_false = NULL; 2150 Label* if_false = NULL;
2110 Label* fall_through = NULL; 2151 Label* fall_through = NULL;
2111 context()->PrepareTest(&materialize_true, &materialize_false, 2152 context()->PrepareTest(&materialize_true, &materialize_false,
2112 &if_true, &if_false, &fall_through); 2153 &if_true, &if_false, &fall_through);
2113 2154
2114 __ JumpIfSmi(rax, if_false); 2155 __ JumpIfSmi(rax, if_false);
2115 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2156 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2116 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2157 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2117 Immediate(1 << Map::kIsUndetectable)); 2158 Immediate(1 << Map::kIsUndetectable));
2159 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2118 Split(not_zero, if_true, if_false, fall_through); 2160 Split(not_zero, if_true, if_false, fall_through);
2119 2161
2120 context()->Plug(if_true, if_false); 2162 context()->Plug(if_true, if_false);
2121 } 2163 }
2122 2164
2123 2165
2124 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2166 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2125 ZoneList<Expression*>* args) { 2167 ZoneList<Expression*>* args) {
2126 ASSERT(args->length() == 1); 2168 ASSERT(args->length() == 1);
2127 2169
2128 VisitForAccumulatorValue(args->at(0)); 2170 VisitForAccumulatorValue(args->at(0));
2129 2171
2130 Label materialize_true, materialize_false; 2172 Label materialize_true, materialize_false;
2131 Label* if_true = NULL; 2173 Label* if_true = NULL;
2132 Label* if_false = NULL; 2174 Label* if_false = NULL;
2133 Label* fall_through = NULL; 2175 Label* fall_through = NULL;
2134 context()->PrepareTest(&materialize_true, &materialize_false, 2176 context()->PrepareTest(&materialize_true, &materialize_false,
2135 &if_true, &if_false, &fall_through); 2177 &if_true, &if_false, &fall_through);
2136 2178
2137 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only 2179 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
2138 // used in a few functions in runtime.js which should not normally be hit by 2180 // used in a few functions in runtime.js which should not normally be hit by
2139 // this compiler. 2181 // this compiler.
2182 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2140 __ jmp(if_false); 2183 __ jmp(if_false);
2141 context()->Plug(if_true, if_false); 2184 context()->Plug(if_true, if_false);
2142 } 2185 }
2143 2186
2144 2187
2145 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2188 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2146 ASSERT(args->length() == 1); 2189 ASSERT(args->length() == 1);
2147 2190
2148 VisitForAccumulatorValue(args->at(0)); 2191 VisitForAccumulatorValue(args->at(0));
2149 2192
2150 Label materialize_true, materialize_false; 2193 Label materialize_true, materialize_false;
2151 Label* if_true = NULL; 2194 Label* if_true = NULL;
2152 Label* if_false = NULL; 2195 Label* if_false = NULL;
2153 Label* fall_through = NULL; 2196 Label* fall_through = NULL;
2154 context()->PrepareTest(&materialize_true, &materialize_false, 2197 context()->PrepareTest(&materialize_true, &materialize_false,
2155 &if_true, &if_false, &fall_through); 2198 &if_true, &if_false, &fall_through);
2156 2199
2157 __ JumpIfSmi(rax, if_false); 2200 __ JumpIfSmi(rax, if_false);
2158 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2201 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2202 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2159 Split(equal, if_true, if_false, fall_through); 2203 Split(equal, if_true, if_false, fall_through);
2160 2204
2161 context()->Plug(if_true, if_false); 2205 context()->Plug(if_true, if_false);
2162 } 2206 }
2163 2207
2164 2208
2165 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2209 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2166 ASSERT(args->length() == 1); 2210 ASSERT(args->length() == 1);
2167 2211
2168 VisitForAccumulatorValue(args->at(0)); 2212 VisitForAccumulatorValue(args->at(0));
2169 2213
2170 Label materialize_true, materialize_false; 2214 Label materialize_true, materialize_false;
2171 Label* if_true = NULL; 2215 Label* if_true = NULL;
2172 Label* if_false = NULL; 2216 Label* if_false = NULL;
2173 Label* fall_through = NULL; 2217 Label* fall_through = NULL;
2174 context()->PrepareTest(&materialize_true, &materialize_false, 2218 context()->PrepareTest(&materialize_true, &materialize_false,
2175 &if_true, &if_false, &fall_through); 2219 &if_true, &if_false, &fall_through);
2176 2220
2177 __ JumpIfSmi(rax, if_false); 2221 __ JumpIfSmi(rax, if_false);
2178 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); 2222 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
2223 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2179 Split(equal, if_true, if_false, fall_through); 2224 Split(equal, if_true, if_false, fall_through);
2180 2225
2181 context()->Plug(if_true, if_false); 2226 context()->Plug(if_true, if_false);
2182 } 2227 }
2183 2228
2184 2229
2185 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2230 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2186 ASSERT(args->length() == 1); 2231 ASSERT(args->length() == 1);
2187 2232
2188 VisitForAccumulatorValue(args->at(0)); 2233 VisitForAccumulatorValue(args->at(0));
2189 2234
2190 Label materialize_true, materialize_false; 2235 Label materialize_true, materialize_false;
2191 Label* if_true = NULL; 2236 Label* if_true = NULL;
2192 Label* if_false = NULL; 2237 Label* if_false = NULL;
2193 Label* fall_through = NULL; 2238 Label* fall_through = NULL;
2194 context()->PrepareTest(&materialize_true, &materialize_false, 2239 context()->PrepareTest(&materialize_true, &materialize_false,
2195 &if_true, &if_false, &fall_through); 2240 &if_true, &if_false, &fall_through);
2196 2241
2197 __ JumpIfSmi(rax, if_false); 2242 __ JumpIfSmi(rax, if_false);
2198 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); 2243 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
2244 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2199 Split(equal, if_true, if_false, fall_through); 2245 Split(equal, if_true, if_false, fall_through);
2200 2246
2201 context()->Plug(if_true, if_false); 2247 context()->Plug(if_true, if_false);
2202 } 2248 }
2203 2249
2204 2250
2205 2251
2206 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2252 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2207 ASSERT(args->length() == 0); 2253 ASSERT(args->length() == 0);
2208 2254
(...skipping 11 matching lines...) Expand all
2220 Label check_frame_marker; 2266 Label check_frame_marker;
2221 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), 2267 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset),
2222 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2268 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2223 __ j(not_equal, &check_frame_marker); 2269 __ j(not_equal, &check_frame_marker);
2224 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 2270 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2225 2271
2226 // Check the marker in the calling frame. 2272 // Check the marker in the calling frame.
2227 __ bind(&check_frame_marker); 2273 __ bind(&check_frame_marker);
2228 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), 2274 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset),
2229 Smi::FromInt(StackFrame::CONSTRUCT)); 2275 Smi::FromInt(StackFrame::CONSTRUCT));
2276 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2230 Split(equal, if_true, if_false, fall_through); 2277 Split(equal, if_true, if_false, fall_through);
2231 2278
2232 context()->Plug(if_true, if_false); 2279 context()->Plug(if_true, if_false);
2233 } 2280 }
2234 2281
2235 2282
2236 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2283 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2237 ASSERT(args->length() == 2); 2284 ASSERT(args->length() == 2);
2238 2285
2239 // Load the two objects into registers and perform the comparison. 2286 // Load the two objects into registers and perform the comparison.
2240 VisitForStackValue(args->at(0)); 2287 VisitForStackValue(args->at(0));
2241 VisitForAccumulatorValue(args->at(1)); 2288 VisitForAccumulatorValue(args->at(1));
2242 2289
2243 Label materialize_true, materialize_false; 2290 Label materialize_true, materialize_false;
2244 Label* if_true = NULL; 2291 Label* if_true = NULL;
2245 Label* if_false = NULL; 2292 Label* if_false = NULL;
2246 Label* fall_through = NULL; 2293 Label* fall_through = NULL;
2247 context()->PrepareTest(&materialize_true, &materialize_false, 2294 context()->PrepareTest(&materialize_true, &materialize_false,
2248 &if_true, &if_false, &fall_through); 2295 &if_true, &if_false, &fall_through);
2249 2296
2250 __ pop(rbx); 2297 __ pop(rbx);
2251 __ cmpq(rax, rbx); 2298 __ cmpq(rax, rbx);
2299 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2252 Split(equal, if_true, if_false, fall_through); 2300 Split(equal, if_true, if_false, fall_through);
2253 2301
2254 context()->Plug(if_true, if_false); 2302 context()->Plug(if_true, if_false);
2255 } 2303 }
2256 2304
2257 2305
2258 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2306 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2259 ASSERT(args->length() == 1); 2307 ASSERT(args->length() == 1);
2260 2308
2261 // ArgumentsAccessStub expects the key in rdx and the formal 2309 // ArgumentsAccessStub expects the key in rdx and the formal
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
2815 2863
2816 Label materialize_true, materialize_false; 2864 Label materialize_true, materialize_false;
2817 Label* if_true = NULL; 2865 Label* if_true = NULL;
2818 Label* if_false = NULL; 2866 Label* if_false = NULL;
2819 Label* fall_through = NULL; 2867 Label* fall_through = NULL;
2820 context()->PrepareTest(&materialize_true, &materialize_false, 2868 context()->PrepareTest(&materialize_true, &materialize_false,
2821 &if_true, &if_false, &fall_through); 2869 &if_true, &if_false, &fall_through);
2822 2870
2823 __ testl(FieldOperand(rax, String::kHashFieldOffset), 2871 __ testl(FieldOperand(rax, String::kHashFieldOffset),
2824 Immediate(String::kContainsCachedArrayIndexMask)); 2872 Immediate(String::kContainsCachedArrayIndexMask));
2873 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2825 __ j(zero, if_true); 2874 __ j(zero, if_true);
2826 __ jmp(if_false); 2875 __ jmp(if_false);
2827 2876
2828 context()->Plug(if_true, if_false); 2877 context()->Plug(if_true, if_false);
2829 } 2878 }
2830 2879
2831 2880
2832 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 2881 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
2833 ASSERT(args->length() == 1); 2882 ASSERT(args->length() == 1);
2834 2883
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2936 2985
2937 case Token::NOT: { 2986 case Token::NOT: {
2938 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2987 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2939 Label materialize_true, materialize_false; 2988 Label materialize_true, materialize_false;
2940 Label* if_true = NULL; 2989 Label* if_true = NULL;
2941 Label* if_false = NULL; 2990 Label* if_false = NULL;
2942 Label* fall_through = NULL; 2991 Label* fall_through = NULL;
2943 // Notice that the labels are swapped. 2992 // Notice that the labels are swapped.
2944 context()->PrepareTest(&materialize_true, &materialize_false, 2993 context()->PrepareTest(&materialize_true, &materialize_false,
2945 &if_false, &if_true, &fall_through); 2994 &if_false, &if_true, &fall_through);
2995 if (context()->IsTest()) ForwardBailoutToChild(expr);
2946 VisitForControl(expr->expression(), if_true, if_false, fall_through); 2996 VisitForControl(expr->expression(), if_true, if_false, fall_through);
2947 context()->Plug(if_false, if_true); // Labels swapped. 2997 context()->Plug(if_false, if_true); // Labels swapped.
2948 break; 2998 break;
2949 } 2999 }
2950 3000
2951 case Token::TYPEOF: { 3001 case Token::TYPEOF: {
2952 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3002 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2953 { StackValueContext context(this); 3003 { StackValueContext context(this);
2954 VisitForTypeofValue(expr->expression()); 3004 VisitForTypeofValue(expr->expression());
2955 } 3005 }
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
3057 EmitNamedPropertyLoad(prop); 3107 EmitNamedPropertyLoad(prop);
3058 } else { 3108 } else {
3059 VisitForStackValue(prop->obj()); 3109 VisitForStackValue(prop->obj());
3060 VisitForAccumulatorValue(prop->key()); 3110 VisitForAccumulatorValue(prop->key());
3061 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 3111 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack
3062 __ push(rax); // Copy of key, needed for later store. 3112 __ push(rax); // Copy of key, needed for later store.
3063 EmitKeyedPropertyLoad(prop); 3113 EmitKeyedPropertyLoad(prop);
3064 } 3114 }
3065 } 3115 }
3066 3116
3117 // We need a second deoptimization point after loading the value
3118 // in case evaluating the property load my have a side effect.
3119 PrepareForBailout(expr->increment(), TOS_REG);
3120
3067 // Call ToNumber only if operand is not a smi. 3121 // Call ToNumber only if operand is not a smi.
3068 NearLabel no_conversion; 3122 NearLabel no_conversion;
3069 Condition is_smi; 3123 Condition is_smi;
3070 is_smi = masm_->CheckSmi(rax); 3124 is_smi = masm_->CheckSmi(rax);
3071 __ j(is_smi, &no_conversion); 3125 __ j(is_smi, &no_conversion);
3072 __ push(rax); 3126 __ push(rax);
3073 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 3127 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
3074 __ bind(&no_conversion); 3128 __ bind(&no_conversion);
3075 3129
3076 // Save result for postfix expressions. 3130 // Save result for postfix expressions.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3126 __ bind(&done); 3180 __ bind(&done);
3127 3181
3128 // Store the value returned in rax. 3182 // Store the value returned in rax.
3129 switch (assign_type) { 3183 switch (assign_type) {
3130 case VARIABLE: 3184 case VARIABLE:
3131 if (expr->is_postfix()) { 3185 if (expr->is_postfix()) {
3132 // Perform the assignment as if via '='. 3186 // Perform the assignment as if via '='.
3133 { EffectContext context(this); 3187 { EffectContext context(this);
3134 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3188 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3135 Token::ASSIGN); 3189 Token::ASSIGN);
3190 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3136 context.Plug(rax); 3191 context.Plug(rax);
3137 } 3192 }
3138 // For all contexts except kEffect: We have the result on 3193 // For all contexts except kEffect: We have the result on
3139 // top of the stack. 3194 // top of the stack.
3140 if (!context()->IsEffect()) { 3195 if (!context()->IsEffect()) {
3141 context()->PlugTOS(); 3196 context()->PlugTOS();
3142 } 3197 }
3143 } else { 3198 } else {
3144 // Perform the assignment as if via '='. 3199 // Perform the assignment as if via '='.
3145 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3200 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3146 Token::ASSIGN); 3201 Token::ASSIGN);
3202 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3147 context()->Plug(rax); 3203 context()->Plug(rax);
3148 } 3204 }
3149 break; 3205 break;
3150 case NAMED_PROPERTY: { 3206 case NAMED_PROPERTY: {
3151 __ Move(rcx, prop->key()->AsLiteral()->handle()); 3207 __ Move(rcx, prop->key()->AsLiteral()->handle());
3152 __ pop(rdx); 3208 __ pop(rdx);
3153 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3209 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3154 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3210 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3211 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3155 if (expr->is_postfix()) { 3212 if (expr->is_postfix()) {
3156 if (!context()->IsEffect()) { 3213 if (!context()->IsEffect()) {
3157 context()->PlugTOS(); 3214 context()->PlugTOS();
3158 } 3215 }
3159 } else { 3216 } else {
3160 context()->Plug(rax); 3217 context()->Plug(rax);
3161 } 3218 }
3162 break; 3219 break;
3163 } 3220 }
3164 case KEYED_PROPERTY: { 3221 case KEYED_PROPERTY: {
3165 __ pop(rcx); 3222 __ pop(rcx);
3166 __ pop(rdx); 3223 __ pop(rdx);
3167 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 3224 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
3168 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3225 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3226 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3169 if (expr->is_postfix()) { 3227 if (expr->is_postfix()) {
3170 if (!context()->IsEffect()) { 3228 if (!context()->IsEffect()) {
3171 context()->PlugTOS(); 3229 context()->PlugTOS();
3172 } 3230 }
3173 } else { 3231 } else {
3174 context()->Plug(rax); 3232 context()->Plug(rax);
3175 } 3233 }
3176 break; 3234 break;
3177 } 3235 }
3178 } 3236 }
3179 } 3237 }
3180 3238
3181 3239
3182 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 3240 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
3183 VariableProxy* proxy = expr->AsVariableProxy(); 3241 VariableProxy* proxy = expr->AsVariableProxy();
3184 ASSERT(!context()->IsEffect()); 3242 ASSERT(!context()->IsEffect());
3185 ASSERT(!context()->IsTest()); 3243 ASSERT(!context()->IsTest());
3186 3244
3187 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { 3245 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
3188 Comment cmnt(masm_, "Global variable"); 3246 Comment cmnt(masm_, "Global variable");
3189 __ Move(rcx, proxy->name()); 3247 __ Move(rcx, proxy->name());
3190 __ movq(rax, GlobalObjectOperand()); 3248 __ movq(rax, GlobalObjectOperand());
3191 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3249 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3192 // Use a regular load, not a contextual load, to avoid a reference 3250 // Use a regular load, not a contextual load, to avoid a reference
3193 // error. 3251 // error.
3194 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3252 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3253 PrepareForBailout(expr, TOS_REG);
3195 context()->Plug(rax); 3254 context()->Plug(rax);
3196 } else if (proxy != NULL && 3255 } else if (proxy != NULL &&
3197 proxy->var()->AsSlot() != NULL && 3256 proxy->var()->AsSlot() != NULL &&
3198 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { 3257 proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
3199 Label done, slow; 3258 Label done, slow;
3200 3259
3201 // Generate code for loading from variables potentially shadowed 3260 // Generate code for loading from variables potentially shadowed
3202 // by eval-introduced variables. 3261 // by eval-introduced variables.
3203 Slot* slot = proxy->var()->AsSlot(); 3262 Slot* slot = proxy->var()->AsSlot();
3204 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); 3263 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
3205 3264
3206 __ bind(&slow); 3265 __ bind(&slow);
3207 __ push(rsi); 3266 __ push(rsi);
3208 __ Push(proxy->name()); 3267 __ Push(proxy->name());
3209 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3268 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3269 PrepareForBailout(expr, TOS_REG);
3210 __ bind(&done); 3270 __ bind(&done);
3211 3271
3212 context()->Plug(rax); 3272 context()->Plug(rax);
3213 } else { 3273 } else {
3214 // This expression cannot throw a reference error at the top level. 3274 // This expression cannot throw a reference error at the top level.
3215 Visit(expr); 3275 Visit(expr);
3216 } 3276 }
3217 } 3277 }
3218 3278
3219 3279
(...skipping 10 matching lines...) Expand all
3230 if (right_literal == NULL) return false; 3290 if (right_literal == NULL) return false;
3231 Handle<Object> right_literal_value = right_literal->handle(); 3291 Handle<Object> right_literal_value = right_literal->handle();
3232 if (!right_literal_value->IsString()) return false; 3292 if (!right_literal_value->IsString()) return false;
3233 UnaryOperation* left_unary = left->AsUnaryOperation(); 3293 UnaryOperation* left_unary = left->AsUnaryOperation();
3234 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; 3294 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
3235 Handle<String> check = Handle<String>::cast(right_literal_value); 3295 Handle<String> check = Handle<String>::cast(right_literal_value);
3236 3296
3237 { AccumulatorValueContext context(this); 3297 { AccumulatorValueContext context(this);
3238 VisitForTypeofValue(left_unary->expression()); 3298 VisitForTypeofValue(left_unary->expression());
3239 } 3299 }
3300 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3240 3301
3241 if (check->Equals(Heap::number_symbol())) { 3302 if (check->Equals(Heap::number_symbol())) {
3242 Condition is_smi = masm_->CheckSmi(rax); 3303 Condition is_smi = masm_->CheckSmi(rax);
3243 __ j(is_smi, if_true); 3304 __ j(is_smi, if_true);
3244 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 3305 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
3245 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 3306 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
3246 Split(equal, if_true, if_false, fall_through); 3307 Split(equal, if_true, if_false, fall_through);
3247 } else if (check->Equals(Heap::string_symbol())) { 3308 } else if (check->Equals(Heap::string_symbol())) {
3248 Condition is_smi = masm_->CheckSmi(rax); 3309 Condition is_smi = masm_->CheckSmi(rax);
3249 __ j(is_smi, if_false); 3310 __ j(is_smi, if_false);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
3323 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { 3384 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
3324 context()->Plug(if_true, if_false); 3385 context()->Plug(if_true, if_false);
3325 return; 3386 return;
3326 } 3387 }
3327 3388
3328 VisitForStackValue(expr->left()); 3389 VisitForStackValue(expr->left());
3329 switch (op) { 3390 switch (op) {
3330 case Token::IN: 3391 case Token::IN:
3331 VisitForStackValue(expr->right()); 3392 VisitForStackValue(expr->right());
3332 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3393 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3394 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
3333 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 3395 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
3334 Split(equal, if_true, if_false, fall_through); 3396 Split(equal, if_true, if_false, fall_through);
3335 break; 3397 break;
3336 3398
3337 case Token::INSTANCEOF: { 3399 case Token::INSTANCEOF: {
3338 VisitForStackValue(expr->right()); 3400 VisitForStackValue(expr->right());
3339 InstanceofStub stub(InstanceofStub::kNoFlags); 3401 InstanceofStub stub(InstanceofStub::kNoFlags);
3340 __ CallStub(&stub); 3402 __ CallStub(&stub);
3403 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3341 __ testq(rax, rax); 3404 __ testq(rax, rax);
3342 // The stub returns 0 for true. 3405 // The stub returns 0 for true.
3343 Split(zero, if_true, if_false, fall_through); 3406 Split(zero, if_true, if_false, fall_through);
3344 break; 3407 break;
3345 } 3408 }
3346 3409
3347 default: { 3410 default: {
3348 VisitForAccumulatorValue(expr->right()); 3411 VisitForAccumulatorValue(expr->right());
3349 Condition cc = no_condition; 3412 Condition cc = no_condition;
3350 bool strict = false; 3413 bool strict = false;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3389 __ SmiCompare(rdx, rax); 3452 __ SmiCompare(rdx, rax);
3390 Split(cc, if_true, if_false, NULL); 3453 Split(cc, if_true, if_false, NULL);
3391 __ bind(&slow_case); 3454 __ bind(&slow_case);
3392 } 3455 }
3393 3456
3394 CompareFlags flags = inline_smi_code 3457 CompareFlags flags = inline_smi_code
3395 ? NO_SMI_COMPARE_IN_STUB 3458 ? NO_SMI_COMPARE_IN_STUB
3396 : NO_COMPARE_FLAGS; 3459 : NO_COMPARE_FLAGS;
3397 CompareStub stub(cc, strict, flags); 3460 CompareStub stub(cc, strict, flags);
3398 __ CallStub(&stub); 3461 __ CallStub(&stub);
3462
3463 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3399 __ testq(rax, rax); 3464 __ testq(rax, rax);
3400 Split(cc, if_true, if_false, fall_through); 3465 Split(cc, if_true, if_false, fall_through);
3401 } 3466 }
3402 } 3467 }
3403 3468
3404 // Convert the result of the comparison into one expected for this 3469 // Convert the result of the comparison into one expected for this
3405 // expression's context. 3470 // expression's context.
3406 context()->Plug(if_true, if_false); 3471 context()->Plug(if_true, if_false);
3407 } 3472 }
3408 3473
3409 3474
3410 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { 3475 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
3411 Comment cmnt(masm_, "[ CompareToNull"); 3476 Comment cmnt(masm_, "[ CompareToNull");
3412 Label materialize_true, materialize_false; 3477 Label materialize_true, materialize_false;
3413 Label* if_true = NULL; 3478 Label* if_true = NULL;
3414 Label* if_false = NULL; 3479 Label* if_false = NULL;
3415 Label* fall_through = NULL; 3480 Label* fall_through = NULL;
3416 context()->PrepareTest(&materialize_true, &materialize_false, 3481 context()->PrepareTest(&materialize_true, &materialize_false,
3417 &if_true, &if_false, &fall_through); 3482 &if_true, &if_false, &fall_through);
3418 3483
3419 VisitForAccumulatorValue(expr->expression()); 3484 VisitForAccumulatorValue(expr->expression());
3485 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3420 __ CompareRoot(rax, Heap::kNullValueRootIndex); 3486 __ CompareRoot(rax, Heap::kNullValueRootIndex);
3421 if (expr->is_strict()) { 3487 if (expr->is_strict()) {
3422 Split(equal, if_true, if_false, fall_through); 3488 Split(equal, if_true, if_false, fall_through);
3423 } else { 3489 } else {
3424 __ j(equal, if_true); 3490 __ j(equal, if_true);
3425 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 3491 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
3426 __ j(equal, if_true); 3492 __ j(equal, if_true);
3427 Condition is_smi = masm_->CheckSmi(rax); 3493 Condition is_smi = masm_->CheckSmi(rax);
3428 __ j(is_smi, if_false); 3494 __ j(is_smi, if_false);
3429 // It can be an undetectable object. 3495 // It can be an undetectable object.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3521 __ ret(0); 3587 __ ret(0);
3522 } 3588 }
3523 3589
3524 3590
3525 #undef __ 3591 #undef __
3526 3592
3527 3593
3528 } } // namespace v8::internal 3594 } } // namespace v8::internal
3529 3595
3530 #endif // V8_TARGET_ARCH_X64 3596 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698