| OLD | NEW |
| 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 25 matching lines...) Expand all Loading... |
| 36 #include "full-codegen.h" | 36 #include "full-codegen.h" |
| 37 #include "parser.h" | 37 #include "parser.h" |
| 38 #include "scopes.h" | 38 #include "scopes.h" |
| 39 #include "stub-cache.h" | 39 #include "stub-cache.h" |
| 40 | 40 |
| 41 namespace v8 { | 41 namespace v8 { |
| 42 namespace internal { | 42 namespace internal { |
| 43 | 43 |
| 44 #define __ ACCESS_MASM(masm_) | 44 #define __ ACCESS_MASM(masm_) |
| 45 | 45 |
| 46 static AstId GetPropertyId(Property* property) { |
| 47 if (property->is_synthetic()) return kNoAstId; |
| 48 return property->id(); |
| 49 } |
| 50 |
| 51 |
| 46 // Generate code for a JS function. On entry to the function the receiver | 52 // Generate code for a JS function. On entry to the function the receiver |
| 47 // and arguments have been pushed on the stack left to right, with the | 53 // and arguments have been pushed on the stack left to right, with the |
| 48 // return address on top of them. The actual argument count matches the | 54 // return address on top of them. The actual argument count matches the |
| 49 // formal parameter count expected by the function. | 55 // formal parameter count expected by the function. |
| 50 // | 56 // |
| 51 // The live registers are: | 57 // The live registers are: |
| 52 // o edi: the JS function object being called (ie, ourselves) | 58 // o edi: the JS function object being called (ie, ourselves) |
| 53 // o esi: our context | 59 // o esi: our context |
| 54 // o ebp: our caller's frame pointer | 60 // o ebp: our caller's frame pointer |
| 55 // o esp: stack pointer (pointing to return address) | 61 // o esp: stack pointer (pointing to return address) |
| (...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 __ j(not_equal, &next_test); | 731 __ j(not_equal, &next_test); |
| 726 __ Drop(1); // Switch value is no longer needed. | 732 __ Drop(1); // Switch value is no longer needed. |
| 727 __ jmp(clause->body_target()->entry_label()); | 733 __ jmp(clause->body_target()->entry_label()); |
| 728 __ bind(&slow_case); | 734 __ bind(&slow_case); |
| 729 } | 735 } |
| 730 | 736 |
| 731 // Record position before stub call for type feedback. | 737 // Record position before stub call for type feedback. |
| 732 SetSourcePosition(clause->position()); | 738 SetSourcePosition(clause->position()); |
| 733 | 739 |
| 734 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 740 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
| 735 __ call(ic, RelocInfo::CODE_TARGET); | 741 __ call(ic, RelocInfo::CODE_TARGET, clause->label()->id()); |
| 736 | 742 |
| 737 __ test(eax, Operand(eax)); | 743 __ test(eax, Operand(eax)); |
| 738 __ j(not_equal, &next_test); | 744 __ j(not_equal, &next_test); |
| 739 __ Drop(1); // Switch value is no longer needed. | 745 __ Drop(1); // Switch value is no longer needed. |
| 740 __ jmp(clause->body_target()->entry_label()); | 746 __ jmp(clause->body_target()->entry_label()); |
| 741 } | 747 } |
| 742 | 748 |
| 743 // Discard the test value and jump to the default if present, otherwise to | 749 // Discard the test value and jump to the default if present, otherwise to |
| 744 // the end of the statement. | 750 // the end of the statement. |
| 745 __ bind(&next_test); | 751 __ bind(&next_test); |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1097 obj_proxy->IsArguments() && | 1103 obj_proxy->IsArguments() && |
| 1098 key_literal->handle()->IsSmi()) { | 1104 key_literal->handle()->IsSmi()) { |
| 1099 // Load arguments object if there are no eval-introduced | 1105 // Load arguments object if there are no eval-introduced |
| 1100 // variables. Then load the argument from the arguments | 1106 // variables. Then load the argument from the arguments |
| 1101 // object using keyed load. | 1107 // object using keyed load. |
| 1102 __ mov(edx, | 1108 __ mov(edx, |
| 1103 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), | 1109 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
| 1104 slow)); | 1110 slow)); |
| 1105 __ mov(eax, Immediate(key_literal->handle())); | 1111 __ mov(eax, Immediate(key_literal->handle())); |
| 1106 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1112 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1107 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1113 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); |
| 1108 __ jmp(done); | 1114 __ jmp(done); |
| 1109 } | 1115 } |
| 1110 } | 1116 } |
| 1111 } | 1117 } |
| 1112 } | 1118 } |
| 1113 } | 1119 } |
| 1114 | 1120 |
| 1115 | 1121 |
| 1116 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1122 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
| 1117 // Four cases: non-this global variables, lookup slots, all other | 1123 // Four cases: non-this global variables, lookup slots, all other |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1183 // Assert that the key is a smi. | 1189 // Assert that the key is a smi. |
| 1184 Literal* key_literal = property->key()->AsLiteral(); | 1190 Literal* key_literal = property->key()->AsLiteral(); |
| 1185 ASSERT_NOT_NULL(key_literal); | 1191 ASSERT_NOT_NULL(key_literal); |
| 1186 ASSERT(key_literal->handle()->IsSmi()); | 1192 ASSERT(key_literal->handle()->IsSmi()); |
| 1187 | 1193 |
| 1188 // Load the key. | 1194 // Load the key. |
| 1189 __ mov(eax, Immediate(key_literal->handle())); | 1195 __ mov(eax, Immediate(key_literal->handle())); |
| 1190 | 1196 |
| 1191 // Do a keyed property load. | 1197 // Do a keyed property load. |
| 1192 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1198 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1193 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1199 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); |
| 1194 | 1200 |
| 1195 // Drop key and object left on the stack by IC. | 1201 // Drop key and object left on the stack by IC. |
| 1196 context()->Plug(eax); | 1202 context()->Plug(eax); |
| 1197 } | 1203 } |
| 1198 } | 1204 } |
| 1199 | 1205 |
| 1200 | 1206 |
| 1201 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1207 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1202 Comment cmnt(masm_, "[ RegExpLiteral"); | 1208 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 1203 NearLabel materialized; | 1209 NearLabel materialized; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1288 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1294 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1289 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1295 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
| 1290 // Fall through. | 1296 // Fall through. |
| 1291 case ObjectLiteral::Property::COMPUTED: | 1297 case ObjectLiteral::Property::COMPUTED: |
| 1292 if (key->handle()->IsSymbol()) { | 1298 if (key->handle()->IsSymbol()) { |
| 1293 if (property->emit_store()) { | 1299 if (property->emit_store()) { |
| 1294 VisitForAccumulatorValue(value); | 1300 VisitForAccumulatorValue(value); |
| 1295 __ mov(ecx, Immediate(key->handle())); | 1301 __ mov(ecx, Immediate(key->handle())); |
| 1296 __ mov(edx, Operand(esp, 0)); | 1302 __ mov(edx, Operand(esp, 0)); |
| 1297 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1303 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1298 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1304 EmitCallIC(ic, RelocInfo::CODE_TARGET, key->id()); |
| 1299 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1305 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1300 } else { | 1306 } else { |
| 1301 VisitForEffect(value); | 1307 VisitForEffect(value); |
| 1302 } | 1308 } |
| 1303 break; | 1309 break; |
| 1304 } | 1310 } |
| 1305 // Fall through. | 1311 // Fall through. |
| 1306 case ObjectLiteral::Property::PROTOTYPE: | 1312 case ObjectLiteral::Property::PROTOTYPE: |
| 1307 __ push(Operand(esp, 0)); // Duplicate receiver. | 1313 __ push(Operand(esp, 0)); // Duplicate receiver. |
| 1308 VisitForStackValue(key); | 1314 VisitForStackValue(key); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1490 __ push(eax); // Left operand goes on the stack. | 1496 __ push(eax); // Left operand goes on the stack. |
| 1491 VisitForAccumulatorValue(expr->value()); | 1497 VisitForAccumulatorValue(expr->value()); |
| 1492 } | 1498 } |
| 1493 | 1499 |
| 1494 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1500 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1495 ? OVERWRITE_RIGHT | 1501 ? OVERWRITE_RIGHT |
| 1496 : NO_OVERWRITE; | 1502 : NO_OVERWRITE; |
| 1497 SetSourcePosition(expr->position() + 1); | 1503 SetSourcePosition(expr->position() + 1); |
| 1498 AccumulatorValueContext context(this); | 1504 AccumulatorValueContext context(this); |
| 1499 if (ShouldInlineSmiCase(op)) { | 1505 if (ShouldInlineSmiCase(op)) { |
| 1500 EmitInlineSmiBinaryOp(expr, | 1506 EmitInlineSmiBinaryOp(expr->binary_operation(), |
| 1501 op, | 1507 op, |
| 1502 mode, | 1508 mode, |
| 1503 expr->target(), | 1509 expr->target(), |
| 1504 expr->value(), | 1510 expr->value(), |
| 1505 constant); | 1511 constant); |
| 1506 } else { | 1512 } else { |
| 1507 EmitBinaryOp(op, mode); | 1513 EmitBinaryOp(expr->binary_operation(), op, mode); |
| 1508 } | 1514 } |
| 1509 | 1515 |
| 1510 // Deoptimization point in case the binary operation may have side effects. | 1516 // Deoptimization point in case the binary operation may have side effects. |
| 1511 PrepareForBailout(expr->binary_operation(), TOS_REG); | 1517 PrepareForBailout(expr->binary_operation(), TOS_REG); |
| 1512 } else { | 1518 } else { |
| 1513 VisitForAccumulatorValue(expr->value()); | 1519 VisitForAccumulatorValue(expr->value()); |
| 1514 } | 1520 } |
| 1515 | 1521 |
| 1516 // Record source position before possible IC call. | 1522 // Record source position before possible IC call. |
| 1517 SetSourcePosition(expr->position()); | 1523 SetSourcePosition(expr->position()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1530 break; | 1536 break; |
| 1531 } | 1537 } |
| 1532 } | 1538 } |
| 1533 | 1539 |
| 1534 | 1540 |
| 1535 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1541 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 1536 SetSourcePosition(prop->position()); | 1542 SetSourcePosition(prop->position()); |
| 1537 Literal* key = prop->key()->AsLiteral(); | 1543 Literal* key = prop->key()->AsLiteral(); |
| 1538 __ mov(ecx, Immediate(key->handle())); | 1544 __ mov(ecx, Immediate(key->handle())); |
| 1539 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1545 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1540 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1546 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); |
| 1541 } | 1547 } |
| 1542 | 1548 |
| 1543 | 1549 |
| 1544 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1550 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 1545 SetSourcePosition(prop->position()); | 1551 SetSourcePosition(prop->position()); |
| 1546 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1552 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1547 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1553 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); |
| 1548 } | 1554 } |
| 1549 | 1555 |
| 1550 | 1556 |
| 1551 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, | 1557 void FullCodeGenerator::EmitConstantSmiAdd(BinaryOperation* expr, |
| 1552 OverwriteMode mode, | 1558 OverwriteMode mode, |
| 1553 bool left_is_constant_smi, | 1559 bool left_is_constant_smi, |
| 1554 Smi* value) { | 1560 Smi* value) { |
| 1555 NearLabel call_stub; | 1561 NearLabel call_stub; |
| 1556 Label done; | 1562 Label done; |
| 1557 __ add(Operand(eax), Immediate(value)); | 1563 __ add(Operand(eax), Immediate(value)); |
| 1558 __ j(overflow, &call_stub); | 1564 __ j(overflow, &call_stub); |
| 1559 __ test(eax, Immediate(kSmiTagMask)); | 1565 __ test(eax, Immediate(kSmiTagMask)); |
| 1560 __ j(zero, &done); | 1566 __ j(zero, &done); |
| 1561 | 1567 |
| 1562 // Undo the optimistic add operation and call the shared stub. | 1568 // Undo the optimistic add operation and call the shared stub. |
| 1563 __ bind(&call_stub); | 1569 __ bind(&call_stub); |
| 1564 __ sub(Operand(eax), Immediate(value)); | 1570 __ sub(Operand(eax), Immediate(value)); |
| 1565 Token::Value op = Token::ADD; | 1571 Token::Value op = Token::ADD; |
| 1566 TypeRecordingBinaryOpStub stub(op, mode); | 1572 TypeRecordingBinaryOpStub stub(op, mode); |
| 1567 if (left_is_constant_smi) { | 1573 if (left_is_constant_smi) { |
| 1568 __ mov(edx, Immediate(value)); | 1574 __ mov(edx, Immediate(value)); |
| 1569 } else { | 1575 } else { |
| 1570 __ mov(edx, eax); | 1576 __ mov(edx, eax); |
| 1571 __ mov(eax, Immediate(value)); | 1577 __ mov(eax, Immediate(value)); |
| 1572 } | 1578 } |
| 1573 __ CallStub(&stub); | 1579 __ CallStub(&stub, expr->id()); |
| 1574 __ bind(&done); | 1580 __ bind(&done); |
| 1575 context()->Plug(eax); | 1581 context()->Plug(eax); |
| 1576 } | 1582 } |
| 1577 | 1583 |
| 1578 | 1584 |
| 1579 void FullCodeGenerator::EmitConstantSmiSub(Expression* expr, | 1585 void FullCodeGenerator::EmitConstantSmiSub(BinaryOperation* expr, |
| 1580 OverwriteMode mode, | 1586 OverwriteMode mode, |
| 1581 bool left_is_constant_smi, | 1587 bool left_is_constant_smi, |
| 1582 Smi* value) { | 1588 Smi* value) { |
| 1583 Label call_stub, done; | 1589 Label call_stub, done; |
| 1584 if (left_is_constant_smi) { | 1590 if (left_is_constant_smi) { |
| 1585 __ mov(ecx, eax); | 1591 __ mov(ecx, eax); |
| 1586 __ mov(eax, Immediate(value)); | 1592 __ mov(eax, Immediate(value)); |
| 1587 __ sub(Operand(eax), ecx); | 1593 __ sub(Operand(eax), ecx); |
| 1588 } else { | 1594 } else { |
| 1589 __ sub(Operand(eax), Immediate(value)); | 1595 __ sub(Operand(eax), Immediate(value)); |
| 1590 } | 1596 } |
| 1591 __ j(overflow, &call_stub); | 1597 __ j(overflow, &call_stub); |
| 1592 __ test(eax, Immediate(kSmiTagMask)); | 1598 __ test(eax, Immediate(kSmiTagMask)); |
| 1593 __ j(zero, &done); | 1599 __ j(zero, &done); |
| 1594 | 1600 |
| 1595 __ bind(&call_stub); | 1601 __ bind(&call_stub); |
| 1596 if (left_is_constant_smi) { | 1602 if (left_is_constant_smi) { |
| 1597 __ mov(edx, Immediate(value)); | 1603 __ mov(edx, Immediate(value)); |
| 1598 __ mov(eax, ecx); | 1604 __ mov(eax, ecx); |
| 1599 } else { | 1605 } else { |
| 1600 __ add(Operand(eax), Immediate(value)); // Undo the subtraction. | 1606 __ add(Operand(eax), Immediate(value)); // Undo the subtraction. |
| 1601 __ mov(edx, eax); | 1607 __ mov(edx, eax); |
| 1602 __ mov(eax, Immediate(value)); | 1608 __ mov(eax, Immediate(value)); |
| 1603 } | 1609 } |
| 1604 Token::Value op = Token::SUB; | 1610 Token::Value op = Token::SUB; |
| 1605 TypeRecordingBinaryOpStub stub(op, mode); | 1611 TypeRecordingBinaryOpStub stub(op, mode); |
| 1606 __ CallStub(&stub); | 1612 __ CallStub(&stub, expr->id()); |
| 1607 __ bind(&done); | 1613 __ bind(&done); |
| 1608 context()->Plug(eax); | 1614 context()->Plug(eax); |
| 1609 } | 1615 } |
| 1610 | 1616 |
| 1611 | 1617 |
| 1612 void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr, | 1618 void FullCodeGenerator::EmitConstantSmiShiftOp(BinaryOperation* expr, |
| 1613 Token::Value op, | 1619 Token::Value op, |
| 1614 OverwriteMode mode, | 1620 OverwriteMode mode, |
| 1615 Smi* value) { | 1621 Smi* value) { |
| 1616 Label call_stub, smi_case, done; | 1622 Label call_stub, smi_case, done; |
| 1617 int shift_value = value->value() & 0x1f; | 1623 int shift_value = value->value() & 0x1f; |
| 1618 | 1624 |
| 1619 __ test(eax, Immediate(kSmiTagMask)); | 1625 __ test(eax, Immediate(kSmiTagMask)); |
| 1620 __ j(zero, &smi_case); | 1626 __ j(zero, &smi_case); |
| 1621 | 1627 |
| 1622 __ bind(&call_stub); | 1628 __ bind(&call_stub); |
| 1623 __ mov(edx, eax); | 1629 __ mov(edx, eax); |
| 1624 __ mov(eax, Immediate(value)); | 1630 __ mov(eax, Immediate(value)); |
| 1625 TypeRecordingBinaryOpStub stub(op, mode); | 1631 TypeRecordingBinaryOpStub stub(op, mode); |
| 1626 __ CallStub(&stub); | 1632 __ CallStub(&stub, expr->id()); |
| 1627 __ jmp(&done); | 1633 __ jmp(&done); |
| 1628 | 1634 |
| 1629 __ bind(&smi_case); | 1635 __ bind(&smi_case); |
| 1630 switch (op) { | 1636 switch (op) { |
| 1631 case Token::SHL: | 1637 case Token::SHL: |
| 1632 if (shift_value != 0) { | 1638 if (shift_value != 0) { |
| 1633 __ mov(edx, eax); | 1639 __ mov(edx, eax); |
| 1634 if (shift_value > 1) { | 1640 if (shift_value > 1) { |
| 1635 __ shl(edx, shift_value - 1); | 1641 __ shl(edx, shift_value - 1); |
| 1636 } | 1642 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1664 break; | 1670 break; |
| 1665 default: | 1671 default: |
| 1666 UNREACHABLE(); | 1672 UNREACHABLE(); |
| 1667 } | 1673 } |
| 1668 | 1674 |
| 1669 __ bind(&done); | 1675 __ bind(&done); |
| 1670 context()->Plug(eax); | 1676 context()->Plug(eax); |
| 1671 } | 1677 } |
| 1672 | 1678 |
| 1673 | 1679 |
| 1674 void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr, | 1680 void FullCodeGenerator::EmitConstantSmiBitOp(BinaryOperation* expr, |
| 1675 Token::Value op, | 1681 Token::Value op, |
| 1676 OverwriteMode mode, | 1682 OverwriteMode mode, |
| 1677 Smi* value) { | 1683 Smi* value) { |
| 1678 Label smi_case, done; | 1684 Label smi_case, done; |
| 1679 __ test(eax, Immediate(kSmiTagMask)); | 1685 __ test(eax, Immediate(kSmiTagMask)); |
| 1680 __ j(zero, &smi_case); | 1686 __ j(zero, &smi_case); |
| 1681 | 1687 |
| 1682 // The order of the arguments does not matter for bit-ops with a | 1688 // The order of the arguments does not matter for bit-ops with a |
| 1683 // constant operand. | 1689 // constant operand. |
| 1684 __ mov(edx, Immediate(value)); | 1690 __ mov(edx, Immediate(value)); |
| 1685 TypeRecordingBinaryOpStub stub(op, mode); | 1691 TypeRecordingBinaryOpStub stub(op, mode); |
| 1686 __ CallStub(&stub); | 1692 __ CallStub(&stub, expr->id()); |
| 1687 __ jmp(&done); | 1693 __ jmp(&done); |
| 1688 | 1694 |
| 1689 __ bind(&smi_case); | 1695 __ bind(&smi_case); |
| 1690 switch (op) { | 1696 switch (op) { |
| 1691 case Token::BIT_OR: | 1697 case Token::BIT_OR: |
| 1692 __ or_(Operand(eax), Immediate(value)); | 1698 __ or_(Operand(eax), Immediate(value)); |
| 1693 break; | 1699 break; |
| 1694 case Token::BIT_XOR: | 1700 case Token::BIT_XOR: |
| 1695 __ xor_(Operand(eax), Immediate(value)); | 1701 __ xor_(Operand(eax), Immediate(value)); |
| 1696 break; | 1702 break; |
| 1697 case Token::BIT_AND: | 1703 case Token::BIT_AND: |
| 1698 __ and_(Operand(eax), Immediate(value)); | 1704 __ and_(Operand(eax), Immediate(value)); |
| 1699 break; | 1705 break; |
| 1700 default: | 1706 default: |
| 1701 UNREACHABLE(); | 1707 UNREACHABLE(); |
| 1702 } | 1708 } |
| 1703 | 1709 |
| 1704 __ bind(&done); | 1710 __ bind(&done); |
| 1705 context()->Plug(eax); | 1711 context()->Plug(eax); |
| 1706 } | 1712 } |
| 1707 | 1713 |
| 1708 | 1714 |
| 1709 void FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr, | 1715 void FullCodeGenerator::EmitConstantSmiBinaryOp(BinaryOperation* expr, |
| 1710 Token::Value op, | 1716 Token::Value op, |
| 1711 OverwriteMode mode, | 1717 OverwriteMode mode, |
| 1712 bool left_is_constant_smi, | 1718 bool left_is_constant_smi, |
| 1713 Smi* value) { | 1719 Smi* value) { |
| 1714 switch (op) { | 1720 switch (op) { |
| 1715 case Token::BIT_OR: | 1721 case Token::BIT_OR: |
| 1716 case Token::BIT_XOR: | 1722 case Token::BIT_XOR: |
| 1717 case Token::BIT_AND: | 1723 case Token::BIT_AND: |
| 1718 EmitConstantSmiBitOp(expr, op, mode, value); | 1724 EmitConstantSmiBitOp(expr, op, mode, value); |
| 1719 break; | 1725 break; |
| 1720 case Token::SHL: | 1726 case Token::SHL: |
| 1721 case Token::SAR: | 1727 case Token::SAR: |
| 1722 case Token::SHR: | 1728 case Token::SHR: |
| 1723 ASSERT(!left_is_constant_smi); | 1729 ASSERT(!left_is_constant_smi); |
| 1724 EmitConstantSmiShiftOp(expr, op, mode, value); | 1730 EmitConstantSmiShiftOp(expr, op, mode, value); |
| 1725 break; | 1731 break; |
| 1726 case Token::ADD: | 1732 case Token::ADD: |
| 1727 EmitConstantSmiAdd(expr, mode, left_is_constant_smi, value); | 1733 EmitConstantSmiAdd(expr, mode, left_is_constant_smi, value); |
| 1728 break; | 1734 break; |
| 1729 case Token::SUB: | 1735 case Token::SUB: |
| 1730 EmitConstantSmiSub(expr, mode, left_is_constant_smi, value); | 1736 EmitConstantSmiSub(expr, mode, left_is_constant_smi, value); |
| 1731 break; | 1737 break; |
| 1732 default: | 1738 default: |
| 1733 UNREACHABLE(); | 1739 UNREACHABLE(); |
| 1734 } | 1740 } |
| 1735 } | 1741 } |
| 1736 | 1742 |
| 1737 | 1743 |
| 1738 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, | 1744 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 1739 Token::Value op, | 1745 Token::Value op, |
| 1740 OverwriteMode mode, | 1746 OverwriteMode mode, |
| 1741 Expression* left, | 1747 Expression* left, |
| 1742 Expression* right, | 1748 Expression* right, |
| 1743 ConstantOperand constant) { | 1749 ConstantOperand constant) { |
| 1744 if (constant == kRightConstant) { | 1750 if (constant == kRightConstant) { |
| 1745 Smi* value = Smi::cast(*right->AsLiteral()->handle()); | 1751 Smi* value = Smi::cast(*right->AsLiteral()->handle()); |
| 1746 EmitConstantSmiBinaryOp(expr, op, mode, false, value); | 1752 EmitConstantSmiBinaryOp(expr, op, mode, false, value); |
| 1747 return; | 1753 return; |
| 1748 } else if (constant == kLeftConstant) { | 1754 } else if (constant == kLeftConstant) { |
| 1749 Smi* value = Smi::cast(*left->AsLiteral()->handle()); | 1755 Smi* value = Smi::cast(*left->AsLiteral()->handle()); |
| 1750 EmitConstantSmiBinaryOp(expr, op, mode, true, value); | 1756 EmitConstantSmiBinaryOp(expr, op, mode, true, value); |
| 1751 return; | 1757 return; |
| 1752 } | 1758 } |
| 1753 | 1759 |
| 1754 // Do combined smi check of the operands. Left operand is on the | 1760 // Do combined smi check of the operands. Left operand is on the |
| 1755 // stack. Right operand is in eax. | 1761 // stack. Right operand is in eax. |
| 1756 Label done, stub_call, smi_case; | 1762 Label done, stub_call, smi_case; |
| 1757 __ pop(edx); | 1763 __ pop(edx); |
| 1758 __ mov(ecx, eax); | 1764 __ mov(ecx, eax); |
| 1759 __ or_(eax, Operand(edx)); | 1765 __ or_(eax, Operand(edx)); |
| 1760 __ test(eax, Immediate(kSmiTagMask)); | 1766 __ test(eax, Immediate(kSmiTagMask)); |
| 1761 __ j(zero, &smi_case); | 1767 __ j(zero, &smi_case); |
| 1762 | 1768 |
| 1763 __ bind(&stub_call); | 1769 __ bind(&stub_call); |
| 1764 __ mov(eax, ecx); | 1770 __ mov(eax, ecx); |
| 1765 TypeRecordingBinaryOpStub stub(op, mode); | 1771 TypeRecordingBinaryOpStub stub(op, mode); |
| 1766 __ CallStub(&stub); | 1772 __ CallStub(&stub, expr->id()); |
| 1767 __ jmp(&done); | 1773 __ jmp(&done); |
| 1768 | 1774 |
| 1769 __ bind(&smi_case); | 1775 __ bind(&smi_case); |
| 1770 __ mov(eax, edx); // Copy left operand in case of a stub call. | 1776 __ mov(eax, edx); // Copy left operand in case of a stub call. |
| 1771 | 1777 |
| 1772 switch (op) { | 1778 switch (op) { |
| 1773 case Token::SAR: | 1779 case Token::SAR: |
| 1774 __ SmiUntag(eax); | 1780 __ SmiUntag(eax); |
| 1775 __ SmiUntag(ecx); | 1781 __ SmiUntag(ecx); |
| 1776 __ sar_cl(eax); // No checks of result necessary | 1782 __ sar_cl(eax); // No checks of result necessary |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1833 break; | 1839 break; |
| 1834 default: | 1840 default: |
| 1835 UNREACHABLE(); | 1841 UNREACHABLE(); |
| 1836 } | 1842 } |
| 1837 | 1843 |
| 1838 __ bind(&done); | 1844 __ bind(&done); |
| 1839 context()->Plug(eax); | 1845 context()->Plug(eax); |
| 1840 } | 1846 } |
| 1841 | 1847 |
| 1842 | 1848 |
| 1843 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1849 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 1850 Token::Value op, |
| 1844 OverwriteMode mode) { | 1851 OverwriteMode mode) { |
| 1845 __ pop(edx); | 1852 __ pop(edx); |
| 1846 TypeRecordingBinaryOpStub stub(op, mode); | 1853 TypeRecordingBinaryOpStub stub(op, mode); |
| 1847 __ CallStub(&stub); | 1854 __ CallStub(&stub, expr->id()); |
| 1848 context()->Plug(eax); | 1855 context()->Plug(eax); |
| 1849 } | 1856 } |
| 1850 | 1857 |
| 1851 | 1858 |
| 1852 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1859 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 1853 // Invalid left-hand sides are rewritten to have a 'throw | 1860 // Invalid left-hand sides are rewritten to have a 'throw |
| 1854 // ReferenceError' on the left-hand side. | 1861 // ReferenceError' on the left-hand side. |
| 1855 if (!expr->IsValidLeftHandSide()) { | 1862 if (!expr->IsValidLeftHandSide()) { |
| 1856 VisitForEffect(expr); | 1863 VisitForEffect(expr); |
| 1857 return; | 1864 return; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1992 | 1999 |
| 1993 // Record source code position before IC call. | 2000 // Record source code position before IC call. |
| 1994 SetSourcePosition(expr->position()); | 2001 SetSourcePosition(expr->position()); |
| 1995 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 2002 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 1996 if (expr->ends_initialization_block()) { | 2003 if (expr->ends_initialization_block()) { |
| 1997 __ mov(edx, Operand(esp, 0)); | 2004 __ mov(edx, Operand(esp, 0)); |
| 1998 } else { | 2005 } else { |
| 1999 __ pop(edx); | 2006 __ pop(edx); |
| 2000 } | 2007 } |
| 2001 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 2008 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 2002 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2009 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 2003 | 2010 |
| 2004 // If the assignment ends an initialization block, revert to fast case. | 2011 // If the assignment ends an initialization block, revert to fast case. |
| 2005 if (expr->ends_initialization_block()) { | 2012 if (expr->ends_initialization_block()) { |
| 2006 __ push(eax); // Result of assignment, saved even if not needed. | 2013 __ push(eax); // Result of assignment, saved even if not needed. |
| 2007 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 2014 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
| 2008 __ CallRuntime(Runtime::kToFastProperties, 1); | 2015 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 2009 __ pop(eax); | 2016 __ pop(eax); |
| 2010 context()->DropAndPlug(1, eax); | 2017 context()->DropAndPlug(1, eax); |
| 2011 } else { | 2018 } else { |
| 2012 context()->Plug(eax); | 2019 context()->Plug(eax); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2030 | 2037 |
| 2031 __ pop(ecx); | 2038 __ pop(ecx); |
| 2032 if (expr->ends_initialization_block()) { | 2039 if (expr->ends_initialization_block()) { |
| 2033 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. | 2040 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. |
| 2034 } else { | 2041 } else { |
| 2035 __ pop(edx); | 2042 __ pop(edx); |
| 2036 } | 2043 } |
| 2037 // Record source code position before IC call. | 2044 // Record source code position before IC call. |
| 2038 SetSourcePosition(expr->position()); | 2045 SetSourcePosition(expr->position()); |
| 2039 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 2046 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 2040 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2047 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 2041 | 2048 |
| 2042 // If the assignment ends an initialization block, revert to fast case. | 2049 // If the assignment ends an initialization block, revert to fast case. |
| 2043 if (expr->ends_initialization_block()) { | 2050 if (expr->ends_initialization_block()) { |
| 2044 __ pop(edx); | 2051 __ pop(edx); |
| 2045 __ push(eax); // Result of assignment, saved even if not needed. | 2052 __ push(eax); // Result of assignment, saved even if not needed. |
| 2046 __ push(edx); | 2053 __ push(edx); |
| 2047 __ CallRuntime(Runtime::kToFastProperties, 1); | 2054 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 2048 __ pop(eax); | 2055 __ pop(eax); |
| 2049 } | 2056 } |
| 2050 | 2057 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2079 { PreservePositionScope scope(masm()->positions_recorder()); | 2086 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2080 for (int i = 0; i < arg_count; i++) { | 2087 for (int i = 0; i < arg_count; i++) { |
| 2081 VisitForStackValue(args->at(i)); | 2088 VisitForStackValue(args->at(i)); |
| 2082 } | 2089 } |
| 2083 __ Set(ecx, Immediate(name)); | 2090 __ Set(ecx, Immediate(name)); |
| 2084 } | 2091 } |
| 2085 // Record source position of the IC call. | 2092 // Record source position of the IC call. |
| 2086 SetSourcePosition(expr->position()); | 2093 SetSourcePosition(expr->position()); |
| 2087 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2094 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2088 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); | 2095 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); |
| 2089 EmitCallIC(ic, mode); | 2096 EmitCallIC(ic, mode, expr->id()); |
| 2090 RecordJSReturnSite(expr); | 2097 RecordJSReturnSite(expr); |
| 2091 // Restore context register. | 2098 // Restore context register. |
| 2092 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2099 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2093 context()->Plug(eax); | 2100 context()->Plug(eax); |
| 2094 } | 2101 } |
| 2095 | 2102 |
| 2096 | 2103 |
| 2097 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2104 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2098 Expression* key, | 2105 Expression* key, |
| 2099 RelocInfo::Mode mode) { | 2106 RelocInfo::Mode mode) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2112 { PreservePositionScope scope(masm()->positions_recorder()); | 2119 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2113 for (int i = 0; i < arg_count; i++) { | 2120 for (int i = 0; i < arg_count; i++) { |
| 2114 VisitForStackValue(args->at(i)); | 2121 VisitForStackValue(args->at(i)); |
| 2115 } | 2122 } |
| 2116 } | 2123 } |
| 2117 // Record source position of the IC call. | 2124 // Record source position of the IC call. |
| 2118 SetSourcePosition(expr->position()); | 2125 SetSourcePosition(expr->position()); |
| 2119 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2126 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2120 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); | 2127 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); |
| 2121 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2128 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. |
| 2122 EmitCallIC(ic, mode); | 2129 EmitCallIC(ic, mode, expr->id()); |
| 2123 RecordJSReturnSite(expr); | 2130 RecordJSReturnSite(expr); |
| 2124 // Restore context register. | 2131 // Restore context register. |
| 2125 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2132 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2126 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2133 context()->DropAndPlug(1, eax); // Drop the key still on the stack. |
| 2127 } | 2134 } |
| 2128 | 2135 |
| 2129 | 2136 |
| 2130 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2137 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
| 2131 // Code common for calls using the call stub. | 2138 // Code common for calls using the call stub. |
| 2132 ZoneList<Expression*>* args = expr->arguments(); | 2139 ZoneList<Expression*>* args = expr->arguments(); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2264 } | 2271 } |
| 2265 if (prop->is_synthetic()) { | 2272 if (prop->is_synthetic()) { |
| 2266 { PreservePositionScope scope(masm()->positions_recorder()); | 2273 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2267 VisitForAccumulatorValue(prop->key()); | 2274 VisitForAccumulatorValue(prop->key()); |
| 2268 } | 2275 } |
| 2269 // Record source code position for IC call. | 2276 // Record source code position for IC call. |
| 2270 SetSourcePosition(prop->position()); | 2277 SetSourcePosition(prop->position()); |
| 2271 __ pop(edx); // We do not need to keep the receiver. | 2278 __ pop(edx); // We do not need to keep the receiver. |
| 2272 | 2279 |
| 2273 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 2280 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 2274 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2281 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); |
| 2275 // Push result (function). | 2282 // Push result (function). |
| 2276 __ push(eax); | 2283 __ push(eax); |
| 2277 // Push Global receiver. | 2284 // Push Global receiver. |
| 2278 __ mov(ecx, GlobalObjectOperand()); | 2285 __ mov(ecx, GlobalObjectOperand()); |
| 2279 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); | 2286 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); |
| 2280 EmitCallWithStub(expr); | 2287 EmitCallWithStub(expr); |
| 2281 } else { | 2288 } else { |
| 2282 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2289 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
| 2283 } | 2290 } |
| 2284 } | 2291 } |
| (...skipping 1180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3465 int arg_count = args->length(); | 3472 int arg_count = args->length(); |
| 3466 for (int i = 0; i < arg_count; i++) { | 3473 for (int i = 0; i < arg_count; i++) { |
| 3467 VisitForStackValue(args->at(i)); | 3474 VisitForStackValue(args->at(i)); |
| 3468 } | 3475 } |
| 3469 | 3476 |
| 3470 if (expr->is_jsruntime()) { | 3477 if (expr->is_jsruntime()) { |
| 3471 // Call the JS runtime function via a call IC. | 3478 // Call the JS runtime function via a call IC. |
| 3472 __ Set(ecx, Immediate(expr->name())); | 3479 __ Set(ecx, Immediate(expr->name())); |
| 3473 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 3480 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 3474 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); | 3481 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); |
| 3475 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3482 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3476 // Restore context register. | 3483 // Restore context register. |
| 3477 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3484 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3478 } else { | 3485 } else { |
| 3479 // Call the C runtime function. | 3486 // Call the C runtime function. |
| 3480 __ CallRuntime(expr->function(), arg_count); | 3487 __ CallRuntime(expr->function(), arg_count); |
| 3481 } | 3488 } |
| 3482 context()->Plug(eax); | 3489 context()->Plug(eax); |
| 3483 } | 3490 } |
| 3484 | 3491 |
| 3485 | 3492 |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3731 } | 3738 } |
| 3732 | 3739 |
| 3733 // Record position before stub call. | 3740 // Record position before stub call. |
| 3734 SetSourcePosition(expr->position()); | 3741 SetSourcePosition(expr->position()); |
| 3735 | 3742 |
| 3736 // Call stub for +1/-1. | 3743 // Call stub for +1/-1. |
| 3737 __ mov(edx, eax); | 3744 __ mov(edx, eax); |
| 3738 __ mov(eax, Immediate(Smi::FromInt(1))); | 3745 __ mov(eax, Immediate(Smi::FromInt(1))); |
| 3739 TypeRecordingBinaryOpStub stub(expr->binary_op(), | 3746 TypeRecordingBinaryOpStub stub(expr->binary_op(), |
| 3740 NO_OVERWRITE); | 3747 NO_OVERWRITE); |
| 3741 __ CallStub(&stub); | 3748 __ CallStub(&stub, expr->increment()->id()); |
| 3742 __ bind(&done); | 3749 __ bind(&done); |
| 3743 | 3750 |
| 3744 // Store the value returned in eax. | 3751 // Store the value returned in eax. |
| 3745 switch (assign_type) { | 3752 switch (assign_type) { |
| 3746 case VARIABLE: | 3753 case VARIABLE: |
| 3747 if (expr->is_postfix()) { | 3754 if (expr->is_postfix()) { |
| 3748 // Perform the assignment as if via '='. | 3755 // Perform the assignment as if via '='. |
| 3749 { EffectContext context(this); | 3756 { EffectContext context(this); |
| 3750 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3757 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3751 Token::ASSIGN); | 3758 Token::ASSIGN); |
| 3752 } | 3759 } |
| 3753 // For all contexts except EffectContext We have the result on | 3760 // For all contexts except EffectContext We have the result on |
| 3754 // top of the stack. | 3761 // top of the stack. |
| 3755 if (!context()->IsEffect()) { | 3762 if (!context()->IsEffect()) { |
| 3756 context()->PlugTOS(); | 3763 context()->PlugTOS(); |
| 3757 } | 3764 } |
| 3758 } else { | 3765 } else { |
| 3759 // Perform the assignment as if via '='. | 3766 // Perform the assignment as if via '='. |
| 3760 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3767 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3761 Token::ASSIGN); | 3768 Token::ASSIGN); |
| 3762 } | 3769 } |
| 3763 break; | 3770 break; |
| 3764 case NAMED_PROPERTY: { | 3771 case NAMED_PROPERTY: { |
| 3765 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 3772 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 3766 __ pop(edx); | 3773 __ pop(edx); |
| 3767 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3774 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 3768 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3775 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3769 if (expr->is_postfix()) { | 3776 if (expr->is_postfix()) { |
| 3770 if (!context()->IsEffect()) { | 3777 if (!context()->IsEffect()) { |
| 3771 context()->PlugTOS(); | 3778 context()->PlugTOS(); |
| 3772 } | 3779 } |
| 3773 } else { | 3780 } else { |
| 3774 context()->Plug(eax); | 3781 context()->Plug(eax); |
| 3775 } | 3782 } |
| 3776 break; | 3783 break; |
| 3777 } | 3784 } |
| 3778 case KEYED_PROPERTY: { | 3785 case KEYED_PROPERTY: { |
| 3779 __ pop(ecx); | 3786 __ pop(ecx); |
| 3780 __ pop(edx); | 3787 __ pop(edx); |
| 3781 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 3788 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 3782 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3789 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3783 if (expr->is_postfix()) { | 3790 if (expr->is_postfix()) { |
| 3784 // Result is on the stack | 3791 // Result is on the stack |
| 3785 if (!context()->IsEffect()) { | 3792 if (!context()->IsEffect()) { |
| 3786 context()->PlugTOS(); | 3793 context()->PlugTOS(); |
| 3787 } | 3794 } |
| 3788 } else { | 3795 } else { |
| 3789 context()->Plug(eax); | 3796 context()->Plug(eax); |
| 3790 } | 3797 } |
| 3791 break; | 3798 break; |
| 3792 } | 3799 } |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4012 __ test(ecx, Immediate(kSmiTagMask)); | 4019 __ test(ecx, Immediate(kSmiTagMask)); |
| 4013 __ j(not_zero, &slow_case, not_taken); | 4020 __ j(not_zero, &slow_case, not_taken); |
| 4014 __ cmp(edx, Operand(eax)); | 4021 __ cmp(edx, Operand(eax)); |
| 4015 Split(cc, if_true, if_false, NULL); | 4022 Split(cc, if_true, if_false, NULL); |
| 4016 __ bind(&slow_case); | 4023 __ bind(&slow_case); |
| 4017 } | 4024 } |
| 4018 | 4025 |
| 4019 // Record position and call the compare IC. | 4026 // Record position and call the compare IC. |
| 4020 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4027 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| 4021 SetSourcePosition(expr->position()); | 4028 SetSourcePosition(expr->position()); |
| 4022 __ call(ic, RelocInfo::CODE_TARGET); | 4029 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 4023 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4030 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 4024 __ test(eax, Operand(eax)); | 4031 __ test(eax, Operand(eax)); |
| 4025 Split(cc, if_true, if_false, fall_through); | 4032 Split(cc, if_true, if_false, fall_through); |
| 4026 } | 4033 } |
| 4027 } | 4034 } |
| 4028 | 4035 |
| 4029 // Convert the result of the comparison into one expected for this | 4036 // Convert the result of the comparison into one expected for this |
| 4030 // expression's context. | 4037 // expression's context. |
| 4031 context()->Plug(if_true, if_false); | 4038 context()->Plug(if_true, if_false); |
| 4032 } | 4039 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4071 Register FullCodeGenerator::result_register() { | 4078 Register FullCodeGenerator::result_register() { |
| 4072 return eax; | 4079 return eax; |
| 4073 } | 4080 } |
| 4074 | 4081 |
| 4075 | 4082 |
| 4076 Register FullCodeGenerator::context_register() { | 4083 Register FullCodeGenerator::context_register() { |
| 4077 return esi; | 4084 return esi; |
| 4078 } | 4085 } |
| 4079 | 4086 |
| 4080 | 4087 |
| 4081 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { | 4088 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, |
| 4089 RelocInfo::Mode mode, |
| 4090 AstId id) { |
| 4082 ASSERT(mode == RelocInfo::CODE_TARGET || | 4091 ASSERT(mode == RelocInfo::CODE_TARGET || |
| 4083 mode == RelocInfo::CODE_TARGET_CONTEXT); | 4092 mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 4084 switch (ic->kind()) { | 4093 switch (ic->kind()) { |
| 4085 case Code::LOAD_IC: | 4094 case Code::LOAD_IC: |
| 4086 __ IncrementCounter(&Counters::named_load_full, 1); | 4095 __ IncrementCounter(&Counters::named_load_full, 1); |
| 4087 break; | 4096 break; |
| 4088 case Code::KEYED_LOAD_IC: | 4097 case Code::KEYED_LOAD_IC: |
| 4089 __ IncrementCounter(&Counters::keyed_load_full, 1); | 4098 __ IncrementCounter(&Counters::keyed_load_full, 1); |
| 4090 break; | 4099 break; |
| 4091 case Code::STORE_IC: | 4100 case Code::STORE_IC: |
| 4092 __ IncrementCounter(&Counters::named_store_full, 1); | 4101 __ IncrementCounter(&Counters::named_store_full, 1); |
| 4093 break; | 4102 break; |
| 4094 case Code::KEYED_STORE_IC: | 4103 case Code::KEYED_STORE_IC: |
| 4095 __ IncrementCounter(&Counters::keyed_store_full, 1); | 4104 __ IncrementCounter(&Counters::keyed_store_full, 1); |
| 4096 default: | 4105 default: |
| 4097 break; | 4106 break; |
| 4098 } | 4107 } |
| 4099 | 4108 |
| 4100 __ call(ic, mode); | 4109 __ call(ic, mode, id); |
| 4101 | 4110 |
| 4102 // Crankshaft doesn't need patching of inlined loads and stores. | 4111 // Crankshaft doesn't need patching of inlined loads and stores. |
| 4103 // When compiling the snapshot we need to produce code that works | 4112 // When compiling the snapshot we need to produce code that works |
| 4104 // with and without Crankshaft. | 4113 // with and without Crankshaft. |
| 4105 if (V8::UseCrankshaft() && !Serializer::enabled()) { | 4114 if (V8::UseCrankshaft() && !Serializer::enabled()) { |
| 4106 return; | 4115 return; |
| 4107 } | 4116 } |
| 4108 | 4117 |
| 4109 // If we're calling a (keyed) load or store stub, we have to mark | 4118 // If we're calling a (keyed) load or store stub, we have to mark |
| 4110 // the call as containing no inlined code so we will not attempt to | 4119 // the call as containing no inlined code so we will not attempt to |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4163 // And return. | 4172 // And return. |
| 4164 __ ret(0); | 4173 __ ret(0); |
| 4165 } | 4174 } |
| 4166 | 4175 |
| 4167 | 4176 |
| 4168 #undef __ | 4177 #undef __ |
| 4169 | 4178 |
| 4170 } } // namespace v8::internal | 4179 } } // namespace v8::internal |
| 4171 | 4180 |
| 4172 #endif // V8_TARGET_ARCH_IA32 | 4181 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |