OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
6 | 6 |
7 #include "src/ast/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/builtins/builtins-constructor.h" | 9 #include "src/builtins/builtins-constructor.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 __ cmp(ebx, isolate()->factory()->catch_context_map()); | 691 __ cmp(ebx, isolate()->factory()->catch_context_map()); |
692 __ Check(not_equal, kDeclarationInCatchContext); | 692 __ Check(not_equal, kDeclarationInCatchContext); |
693 } | 693 } |
694 } | 694 } |
695 | 695 |
696 | 696 |
697 void FullCodeGenerator::VisitVariableDeclaration( | 697 void FullCodeGenerator::VisitVariableDeclaration( |
698 VariableDeclaration* declaration) { | 698 VariableDeclaration* declaration) { |
699 VariableProxy* proxy = declaration->proxy(); | 699 VariableProxy* proxy = declaration->proxy(); |
700 Variable* variable = proxy->var(); | 700 Variable* variable = proxy->var(); |
701 DCHECK(!variable->binding_needs_init()); | |
702 switch (variable->location()) { | 701 switch (variable->location()) { |
703 case VariableLocation::UNALLOCATED: { | 702 case VariableLocation::UNALLOCATED: { |
| 703 DCHECK(!variable->binding_needs_init()); |
704 globals_->Add(variable->name(), zone()); | 704 globals_->Add(variable->name(), zone()); |
705 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); | 705 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); |
706 DCHECK(!slot.IsInvalid()); | 706 DCHECK(!slot.IsInvalid()); |
707 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); | 707 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); |
708 globals_->Add(isolate()->factory()->undefined_value(), zone()); | 708 globals_->Add(isolate()->factory()->undefined_value(), zone()); |
709 break; | 709 break; |
710 } | 710 } |
711 case VariableLocation::PARAMETER: | 711 case VariableLocation::PARAMETER: |
712 case VariableLocation::LOCAL: | 712 case VariableLocation::LOCAL: |
| 713 if (variable->binding_needs_init()) { |
| 714 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 715 __ mov(StackOperand(variable), |
| 716 Immediate(isolate()->factory()->the_hole_value())); |
| 717 } |
| 718 break; |
| 719 |
713 case VariableLocation::CONTEXT: | 720 case VariableLocation::CONTEXT: |
| 721 if (variable->binding_needs_init()) { |
| 722 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 723 EmitDebugCheckDeclarationContext(variable); |
| 724 __ mov(ContextOperand(esi, variable->index()), |
| 725 Immediate(isolate()->factory()->the_hole_value())); |
| 726 // No write barrier since the hole value is in old space. |
| 727 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 728 } |
714 break; | 729 break; |
715 | 730 |
716 case VariableLocation::LOOKUP: | 731 case VariableLocation::LOOKUP: |
717 case VariableLocation::MODULE: | 732 case VariableLocation::MODULE: |
718 UNREACHABLE(); | 733 UNREACHABLE(); |
719 } | 734 } |
720 } | 735 } |
721 | 736 |
722 void FullCodeGenerator::VisitFunctionDeclaration( | 737 void FullCodeGenerator::VisitFunctionDeclaration( |
723 FunctionDeclaration* declaration) { | 738 FunctionDeclaration* declaration) { |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1042 __ mov(StoreDescriptor::ReceiverRegister(), eax); | 1057 __ mov(StoreDescriptor::ReceiverRegister(), eax); |
1043 __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize)); | 1058 __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize)); |
1044 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); | 1059 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); |
1045 } | 1060 } |
1046 | 1061 |
1047 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1062 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
1048 TypeofMode typeof_mode) { | 1063 TypeofMode typeof_mode) { |
1049 SetExpressionPosition(proxy); | 1064 SetExpressionPosition(proxy); |
1050 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 1065 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); |
1051 Variable* var = proxy->var(); | 1066 Variable* var = proxy->var(); |
1052 DCHECK(!var->binding_needs_init()); | |
1053 | 1067 |
1054 // Two cases: global variables and all other types of variables. | 1068 // Two cases: global variables and all other types of variables. |
1055 switch (var->location()) { | 1069 switch (var->location()) { |
1056 case VariableLocation::UNALLOCATED: { | 1070 case VariableLocation::UNALLOCATED: { |
1057 Comment cmnt(masm_, "[ Global variable"); | 1071 Comment cmnt(masm_, "[ Global variable"); |
1058 EmitGlobalVariableLoad(proxy, typeof_mode); | 1072 EmitGlobalVariableLoad(proxy, typeof_mode); |
1059 context()->Plug(eax); | 1073 context()->Plug(eax); |
1060 break; | 1074 break; |
1061 } | 1075 } |
1062 | 1076 |
1063 case VariableLocation::PARAMETER: | 1077 case VariableLocation::PARAMETER: |
1064 case VariableLocation::LOCAL: | 1078 case VariableLocation::LOCAL: |
1065 case VariableLocation::CONTEXT: { | 1079 case VariableLocation::CONTEXT: { |
1066 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); | 1080 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); |
1067 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1081 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
1068 : "[ Stack variable"); | 1082 : "[ Stack variable"); |
| 1083 |
| 1084 if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { |
| 1085 // Throw a reference error when using an uninitialized let/const |
| 1086 // binding in harmony mode. |
| 1087 Label done; |
| 1088 GetVar(eax, var); |
| 1089 __ cmp(eax, isolate()->factory()->the_hole_value()); |
| 1090 __ j(not_equal, &done, Label::kNear); |
| 1091 __ push(Immediate(var->name())); |
| 1092 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1093 __ bind(&done); |
| 1094 context()->Plug(eax); |
| 1095 break; |
| 1096 } |
1069 context()->Plug(var); | 1097 context()->Plug(var); |
1070 break; | 1098 break; |
1071 } | 1099 } |
1072 | 1100 |
1073 case VariableLocation::LOOKUP: | 1101 case VariableLocation::LOOKUP: |
1074 case VariableLocation::MODULE: | 1102 case VariableLocation::MODULE: |
1075 UNREACHABLE(); | 1103 UNREACHABLE(); |
1076 } | 1104 } |
1077 } | 1105 } |
1078 | 1106 |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1376 } else { | 1404 } else { |
1377 VisitForAccumulatorValue(expr->value()); | 1405 VisitForAccumulatorValue(expr->value()); |
1378 } | 1406 } |
1379 | 1407 |
1380 SetExpressionPosition(expr); | 1408 SetExpressionPosition(expr); |
1381 | 1409 |
1382 // Store the value. | 1410 // Store the value. |
1383 switch (assign_type) { | 1411 switch (assign_type) { |
1384 case VARIABLE: { | 1412 case VARIABLE: { |
1385 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 1413 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
1386 EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); | 1414 EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), |
| 1415 proxy->hole_check_mode()); |
1387 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); | 1416 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); |
1388 context()->Plug(eax); | 1417 context()->Plug(eax); |
1389 break; | 1418 break; |
1390 } | 1419 } |
1391 case NAMED_PROPERTY: | 1420 case NAMED_PROPERTY: |
1392 EmitNamedPropertyAssignment(expr); | 1421 EmitNamedPropertyAssignment(expr); |
1393 break; | 1422 break; |
1394 case KEYED_PROPERTY: | 1423 case KEYED_PROPERTY: |
1395 EmitKeyedPropertyAssignment(expr); | 1424 EmitKeyedPropertyAssignment(expr); |
1396 break; | 1425 break; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1557 FeedbackVectorSlot slot) { | 1586 FeedbackVectorSlot slot) { |
1558 DCHECK(expr->IsValidReferenceExpressionOrThis()); | 1587 DCHECK(expr->IsValidReferenceExpressionOrThis()); |
1559 | 1588 |
1560 Property* prop = expr->AsProperty(); | 1589 Property* prop = expr->AsProperty(); |
1561 LhsKind assign_type = Property::GetAssignType(prop); | 1590 LhsKind assign_type = Property::GetAssignType(prop); |
1562 | 1591 |
1563 switch (assign_type) { | 1592 switch (assign_type) { |
1564 case VARIABLE: { | 1593 case VARIABLE: { |
1565 VariableProxy* proxy = expr->AsVariableProxy(); | 1594 VariableProxy* proxy = expr->AsVariableProxy(); |
1566 EffectContext context(this); | 1595 EffectContext context(this); |
1567 EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); | 1596 EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, |
| 1597 proxy->hole_check_mode()); |
1568 break; | 1598 break; |
1569 } | 1599 } |
1570 case NAMED_PROPERTY: { | 1600 case NAMED_PROPERTY: { |
1571 PushOperand(eax); // Preserve value. | 1601 PushOperand(eax); // Preserve value. |
1572 VisitForAccumulatorValue(prop->obj()); | 1602 VisitForAccumulatorValue(prop->obj()); |
1573 __ Move(StoreDescriptor::ReceiverRegister(), eax); | 1603 __ Move(StoreDescriptor::ReceiverRegister(), eax); |
1574 PopOperand(StoreDescriptor::ValueRegister()); // Restore value. | 1604 PopOperand(StoreDescriptor::ValueRegister()); // Restore value. |
1575 CallStoreIC(slot, prop->key()->AsLiteral()->value()); | 1605 CallStoreIC(slot, prop->key()->AsLiteral()->value()); |
1576 break; | 1606 break; |
1577 } | 1607 } |
(...skipping 20 matching lines...) Expand all Loading... |
1598 Variable* var, MemOperand location) { | 1628 Variable* var, MemOperand location) { |
1599 __ mov(location, eax); | 1629 __ mov(location, eax); |
1600 if (var->IsContextSlot()) { | 1630 if (var->IsContextSlot()) { |
1601 __ mov(edx, eax); | 1631 __ mov(edx, eax); |
1602 int offset = Context::SlotOffset(var->index()); | 1632 int offset = Context::SlotOffset(var->index()); |
1603 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); | 1633 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); |
1604 } | 1634 } |
1605 } | 1635 } |
1606 | 1636 |
1607 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 1637 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, |
1608 FeedbackVectorSlot slot) { | 1638 FeedbackVectorSlot slot, |
1609 DCHECK(!var->binding_needs_init()); | 1639 HoleCheckMode hole_check_mode) { |
1610 if (var->IsUnallocated()) { | 1640 if (var->IsUnallocated()) { |
1611 // Global var, const, or let. | 1641 // Global var, const, or let. |
1612 __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand()); | 1642 __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand()); |
1613 __ mov(StoreDescriptor::ReceiverRegister(), | 1643 __ mov(StoreDescriptor::ReceiverRegister(), |
1614 ContextOperand(StoreDescriptor::ReceiverRegister(), | 1644 ContextOperand(StoreDescriptor::ReceiverRegister(), |
1615 Context::EXTENSION_INDEX)); | 1645 Context::EXTENSION_INDEX)); |
1616 CallStoreIC(slot, var->name()); | 1646 CallStoreIC(slot, var->name()); |
1617 | 1647 |
1618 } else if (var->mode() == CONST && op != Token::INIT) { | 1648 } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { |
1619 if (var->throw_on_const_assignment(language_mode())) { | 1649 DCHECK(!var->IsLookupSlot()); |
| 1650 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 1651 MemOperand location = VarOperand(var, ecx); |
| 1652 // Perform an initialization check for lexically declared variables. |
| 1653 if (hole_check_mode == HoleCheckMode::kRequired) { |
| 1654 Label assign; |
| 1655 __ mov(edx, location); |
| 1656 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 1657 __ j(not_equal, &assign, Label::kNear); |
| 1658 __ push(Immediate(var->name())); |
| 1659 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1660 __ bind(&assign); |
| 1661 } |
| 1662 if (var->mode() != CONST) { |
| 1663 EmitStoreToStackLocalOrContextSlot(var, location); |
| 1664 } else if (var->throw_on_const_assignment(language_mode())) { |
1620 __ CallRuntime(Runtime::kThrowConstAssignError); | 1665 __ CallRuntime(Runtime::kThrowConstAssignError); |
1621 } | 1666 } |
| 1667 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
| 1668 // Initializing assignment to const {this} needs a write barrier. |
| 1669 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 1670 Label uninitialized_this; |
| 1671 MemOperand location = VarOperand(var, ecx); |
| 1672 __ mov(edx, location); |
| 1673 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 1674 __ j(equal, &uninitialized_this); |
| 1675 __ push(Immediate(var->name())); |
| 1676 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1677 __ bind(&uninitialized_this); |
| 1678 EmitStoreToStackLocalOrContextSlot(var, location); |
| 1679 |
1622 } else { | 1680 } else { |
1623 DCHECK(!var->is_this()); | 1681 DCHECK(var->mode() != CONST || op == Token::INIT); |
1624 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 1682 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
1625 DCHECK(!var->IsLookupSlot()); | 1683 DCHECK(!var->IsLookupSlot()); |
| 1684 // Assignment to var or initializing assignment to let/const in harmony |
| 1685 // mode. |
1626 MemOperand location = VarOperand(var, ecx); | 1686 MemOperand location = VarOperand(var, ecx); |
| 1687 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
| 1688 // Check for an uninitialized let binding. |
| 1689 __ mov(edx, location); |
| 1690 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 1691 __ Check(equal, kLetBindingReInitialization); |
| 1692 } |
1627 EmitStoreToStackLocalOrContextSlot(var, location); | 1693 EmitStoreToStackLocalOrContextSlot(var, location); |
1628 } | 1694 } |
1629 } | 1695 } |
1630 | 1696 |
1631 | 1697 |
1632 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1698 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1633 // Assignment to a property, using a named store IC. | 1699 // Assignment to a property, using a named store IC. |
1634 // eax : value | 1700 // eax : value |
1635 // esp[0] : receiver | 1701 // esp[0] : receiver |
1636 Property* prop = expr->target()->AsProperty(); | 1702 Property* prop = expr->target()->AsProperty(); |
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2336 patch_site.EmitPatchInfo(); | 2402 patch_site.EmitPatchInfo(); |
2337 __ bind(&done); | 2403 __ bind(&done); |
2338 | 2404 |
2339 // Store the value returned in eax. | 2405 // Store the value returned in eax. |
2340 switch (assign_type) { | 2406 switch (assign_type) { |
2341 case VARIABLE: { | 2407 case VARIABLE: { |
2342 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2408 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
2343 if (expr->is_postfix()) { | 2409 if (expr->is_postfix()) { |
2344 // Perform the assignment as if via '='. | 2410 // Perform the assignment as if via '='. |
2345 { EffectContext context(this); | 2411 { EffectContext context(this); |
2346 EmitVariableAssignment(proxy->var(), Token::ASSIGN, | 2412 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), |
2347 expr->CountSlot()); | 2413 proxy->hole_check_mode()); |
2348 PrepareForBailoutForId(expr->AssignmentId(), | 2414 PrepareForBailoutForId(expr->AssignmentId(), |
2349 BailoutState::TOS_REGISTER); | 2415 BailoutState::TOS_REGISTER); |
2350 context.Plug(eax); | 2416 context.Plug(eax); |
2351 } | 2417 } |
2352 // For all contexts except EffectContext We have the result on | 2418 // For all contexts except EffectContext We have the result on |
2353 // top of the stack. | 2419 // top of the stack. |
2354 if (!context()->IsEffect()) { | 2420 if (!context()->IsEffect()) { |
2355 context()->PlugTOS(); | 2421 context()->PlugTOS(); |
2356 } | 2422 } |
2357 } else { | 2423 } else { |
2358 // Perform the assignment as if via '='. | 2424 // Perform the assignment as if via '='. |
2359 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); | 2425 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), |
| 2426 proxy->hole_check_mode()); |
2360 PrepareForBailoutForId(expr->AssignmentId(), | 2427 PrepareForBailoutForId(expr->AssignmentId(), |
2361 BailoutState::TOS_REGISTER); | 2428 BailoutState::TOS_REGISTER); |
2362 context()->Plug(eax); | 2429 context()->Plug(eax); |
2363 } | 2430 } |
2364 break; | 2431 break; |
2365 } | 2432 } |
2366 case NAMED_PROPERTY: { | 2433 case NAMED_PROPERTY: { |
2367 PopOperand(StoreDescriptor::ReceiverRegister()); | 2434 PopOperand(StoreDescriptor::ReceiverRegister()); |
2368 CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); | 2435 CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); |
2369 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); | 2436 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2698 isolate->builtins()->OnStackReplacement()->entry(), | 2765 isolate->builtins()->OnStackReplacement()->entry(), |
2699 Assembler::target_address_at(call_target_address, unoptimized_code)); | 2766 Assembler::target_address_at(call_target_address, unoptimized_code)); |
2700 return ON_STACK_REPLACEMENT; | 2767 return ON_STACK_REPLACEMENT; |
2701 } | 2768 } |
2702 | 2769 |
2703 | 2770 |
2704 } // namespace internal | 2771 } // namespace internal |
2705 } // namespace v8 | 2772 } // namespace v8 |
2706 | 2773 |
2707 #endif // V8_TARGET_ARCH_X87 | 2774 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |