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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 | 343 |
344 } else { | 344 } else { |
345 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 345 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
346 { Comment cmnt(masm_, "[ Declarations"); | 346 { Comment cmnt(masm_, "[ Declarations"); |
347 // For named function expressions, declare the function name as a | 347 // For named function expressions, declare the function name as a |
348 // constant. | 348 // constant. |
349 if (scope()->is_function_scope() && scope()->function() != NULL) { | 349 if (scope()->is_function_scope() && scope()->function() != NULL) { |
350 VariableDeclaration* function = scope()->function(); | 350 VariableDeclaration* function = scope()->function(); |
351 DCHECK(function->proxy()->var()->mode() == CONST || | 351 DCHECK(function->proxy()->var()->mode() == CONST || |
352 function->proxy()->var()->mode() == CONST_LEGACY); | 352 function->proxy()->var()->mode() == CONST_LEGACY); |
353 DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED); | 353 DCHECK(!function->proxy()->var()->IsUnallocatedOrGlobalSlot()); |
354 VisitVariableDeclaration(function); | 354 VisitVariableDeclaration(function); |
355 } | 355 } |
356 VisitDeclarations(scope()->declarations()); | 356 VisitDeclarations(scope()->declarations()); |
357 } | 357 } |
358 | 358 |
359 { Comment cmnt(masm_, "[ Stack check"); | 359 { Comment cmnt(masm_, "[ Stack check"); |
360 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); | 360 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); |
361 Label ok; | 361 Label ok; |
362 ExternalReference stack_limit | 362 ExternalReference stack_limit |
363 = ExternalReference::address_of_stack_limit(isolate()); | 363 = ExternalReference::address_of_stack_limit(isolate()); |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
813 void FullCodeGenerator::VisitVariableDeclaration( | 813 void FullCodeGenerator::VisitVariableDeclaration( |
814 VariableDeclaration* declaration) { | 814 VariableDeclaration* declaration) { |
815 // If it was not possible to allocate the variable at compile time, we | 815 // If it was not possible to allocate the variable at compile time, we |
816 // need to "declare" it at runtime to make sure it actually exists in the | 816 // need to "declare" it at runtime to make sure it actually exists in the |
817 // local context. | 817 // local context. |
818 VariableProxy* proxy = declaration->proxy(); | 818 VariableProxy* proxy = declaration->proxy(); |
819 VariableMode mode = declaration->mode(); | 819 VariableMode mode = declaration->mode(); |
820 Variable* variable = proxy->var(); | 820 Variable* variable = proxy->var(); |
821 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; | 821 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; |
822 switch (variable->location()) { | 822 switch (variable->location()) { |
823 case Variable::UNALLOCATED: | 823 case VariableLocation::GLOBAL: |
| 824 case VariableLocation::UNALLOCATED: |
824 globals_->Add(variable->name(), zone()); | 825 globals_->Add(variable->name(), zone()); |
825 globals_->Add(variable->binding_needs_init() | 826 globals_->Add(variable->binding_needs_init() |
826 ? isolate()->factory()->the_hole_value() | 827 ? isolate()->factory()->the_hole_value() |
827 : isolate()->factory()->undefined_value(), zone()); | 828 : isolate()->factory()->undefined_value(), zone()); |
828 break; | 829 break; |
829 | 830 |
830 case Variable::PARAMETER: | 831 case VariableLocation::PARAMETER: |
831 case Variable::LOCAL: | 832 case VariableLocation::LOCAL: |
832 if (hole_init) { | 833 if (hole_init) { |
833 Comment cmnt(masm_, "[ VariableDeclaration"); | 834 Comment cmnt(masm_, "[ VariableDeclaration"); |
834 __ mov(StackOperand(variable), | 835 __ mov(StackOperand(variable), |
835 Immediate(isolate()->factory()->the_hole_value())); | 836 Immediate(isolate()->factory()->the_hole_value())); |
836 } | 837 } |
837 break; | 838 break; |
838 | 839 |
839 case Variable::CONTEXT: | 840 case VariableLocation::CONTEXT: |
840 if (hole_init) { | 841 if (hole_init) { |
841 Comment cmnt(masm_, "[ VariableDeclaration"); | 842 Comment cmnt(masm_, "[ VariableDeclaration"); |
842 EmitDebugCheckDeclarationContext(variable); | 843 EmitDebugCheckDeclarationContext(variable); |
843 __ mov(ContextOperand(esi, variable->index()), | 844 __ mov(ContextOperand(esi, variable->index()), |
844 Immediate(isolate()->factory()->the_hole_value())); | 845 Immediate(isolate()->factory()->the_hole_value())); |
845 // No write barrier since the hole value is in old space. | 846 // No write barrier since the hole value is in old space. |
846 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 847 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
847 } | 848 } |
848 break; | 849 break; |
849 | 850 |
850 case Variable::LOOKUP: { | 851 case VariableLocation::LOOKUP: { |
851 Comment cmnt(masm_, "[ VariableDeclaration"); | 852 Comment cmnt(masm_, "[ VariableDeclaration"); |
852 __ push(esi); | 853 __ push(esi); |
853 __ push(Immediate(variable->name())); | 854 __ push(Immediate(variable->name())); |
854 // VariableDeclaration nodes are always introduced in one of four modes. | 855 // VariableDeclaration nodes are always introduced in one of four modes. |
855 DCHECK(IsDeclaredVariableMode(mode)); | 856 DCHECK(IsDeclaredVariableMode(mode)); |
856 PropertyAttributes attr = | 857 PropertyAttributes attr = |
857 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; | 858 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; |
858 __ push(Immediate(Smi::FromInt(attr))); | 859 __ push(Immediate(Smi::FromInt(attr))); |
859 // Push initial value, if any. | 860 // Push initial value, if any. |
860 // Note: For variables we must not push an initial value (such as | 861 // Note: For variables we must not push an initial value (such as |
861 // 'undefined') because we may have a (legal) redeclaration and we | 862 // 'undefined') because we may have a (legal) redeclaration and we |
862 // must not destroy the current value. | 863 // must not destroy the current value. |
863 if (hole_init) { | 864 if (hole_init) { |
864 __ push(Immediate(isolate()->factory()->the_hole_value())); | 865 __ push(Immediate(isolate()->factory()->the_hole_value())); |
865 } else { | 866 } else { |
866 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. | 867 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. |
867 } | 868 } |
868 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 869 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
869 break; | 870 break; |
870 } | 871 } |
871 } | 872 } |
872 } | 873 } |
873 | 874 |
874 | 875 |
875 void FullCodeGenerator::VisitFunctionDeclaration( | 876 void FullCodeGenerator::VisitFunctionDeclaration( |
876 FunctionDeclaration* declaration) { | 877 FunctionDeclaration* declaration) { |
877 VariableProxy* proxy = declaration->proxy(); | 878 VariableProxy* proxy = declaration->proxy(); |
878 Variable* variable = proxy->var(); | 879 Variable* variable = proxy->var(); |
879 switch (variable->location()) { | 880 switch (variable->location()) { |
880 case Variable::UNALLOCATED: { | 881 case VariableLocation::GLOBAL: |
| 882 case VariableLocation::UNALLOCATED: { |
881 globals_->Add(variable->name(), zone()); | 883 globals_->Add(variable->name(), zone()); |
882 Handle<SharedFunctionInfo> function = | 884 Handle<SharedFunctionInfo> function = |
883 Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_); | 885 Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_); |
884 // Check for stack-overflow exception. | 886 // Check for stack-overflow exception. |
885 if (function.is_null()) return SetStackOverflow(); | 887 if (function.is_null()) return SetStackOverflow(); |
886 globals_->Add(function, zone()); | 888 globals_->Add(function, zone()); |
887 break; | 889 break; |
888 } | 890 } |
889 | 891 |
890 case Variable::PARAMETER: | 892 case VariableLocation::PARAMETER: |
891 case Variable::LOCAL: { | 893 case VariableLocation::LOCAL: { |
892 Comment cmnt(masm_, "[ FunctionDeclaration"); | 894 Comment cmnt(masm_, "[ FunctionDeclaration"); |
893 VisitForAccumulatorValue(declaration->fun()); | 895 VisitForAccumulatorValue(declaration->fun()); |
894 __ mov(StackOperand(variable), result_register()); | 896 __ mov(StackOperand(variable), result_register()); |
895 break; | 897 break; |
896 } | 898 } |
897 | 899 |
898 case Variable::CONTEXT: { | 900 case VariableLocation::CONTEXT: { |
899 Comment cmnt(masm_, "[ FunctionDeclaration"); | 901 Comment cmnt(masm_, "[ FunctionDeclaration"); |
900 EmitDebugCheckDeclarationContext(variable); | 902 EmitDebugCheckDeclarationContext(variable); |
901 VisitForAccumulatorValue(declaration->fun()); | 903 VisitForAccumulatorValue(declaration->fun()); |
902 __ mov(ContextOperand(esi, variable->index()), result_register()); | 904 __ mov(ContextOperand(esi, variable->index()), result_register()); |
903 // We know that we have written a function, which is not a smi. | 905 // We know that we have written a function, which is not a smi. |
904 __ RecordWriteContextSlot(esi, Context::SlotOffset(variable->index()), | 906 __ RecordWriteContextSlot(esi, Context::SlotOffset(variable->index()), |
905 result_register(), ecx, kDontSaveFPRegs, | 907 result_register(), ecx, kDontSaveFPRegs, |
906 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 908 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
907 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 909 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
908 break; | 910 break; |
909 } | 911 } |
910 | 912 |
911 case Variable::LOOKUP: { | 913 case VariableLocation::LOOKUP: { |
912 Comment cmnt(masm_, "[ FunctionDeclaration"); | 914 Comment cmnt(masm_, "[ FunctionDeclaration"); |
913 __ push(esi); | 915 __ push(esi); |
914 __ push(Immediate(variable->name())); | 916 __ push(Immediate(variable->name())); |
915 __ push(Immediate(Smi::FromInt(NONE))); | 917 __ push(Immediate(Smi::FromInt(NONE))); |
916 VisitForStackValue(declaration->fun()); | 918 VisitForStackValue(declaration->fun()); |
917 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 919 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
918 break; | 920 break; |
919 } | 921 } |
920 } | 922 } |
921 } | 923 } |
922 | 924 |
923 | 925 |
924 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { | 926 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { |
925 VariableProxy* proxy = declaration->proxy(); | 927 VariableProxy* proxy = declaration->proxy(); |
926 Variable* variable = proxy->var(); | 928 Variable* variable = proxy->var(); |
927 switch (variable->location()) { | 929 switch (variable->location()) { |
928 case Variable::UNALLOCATED: | 930 case VariableLocation::GLOBAL: |
| 931 case VariableLocation::UNALLOCATED: |
929 // TODO(rossberg) | 932 // TODO(rossberg) |
930 break; | 933 break; |
931 | 934 |
932 case Variable::CONTEXT: { | 935 case VariableLocation::CONTEXT: { |
933 Comment cmnt(masm_, "[ ImportDeclaration"); | 936 Comment cmnt(masm_, "[ ImportDeclaration"); |
934 EmitDebugCheckDeclarationContext(variable); | 937 EmitDebugCheckDeclarationContext(variable); |
935 // TODO(rossberg) | 938 // TODO(rossberg) |
936 break; | 939 break; |
937 } | 940 } |
938 | 941 |
939 case Variable::PARAMETER: | 942 case VariableLocation::PARAMETER: |
940 case Variable::LOCAL: | 943 case VariableLocation::LOCAL: |
941 case Variable::LOOKUP: | 944 case VariableLocation::LOOKUP: |
942 UNREACHABLE(); | 945 UNREACHABLE(); |
943 } | 946 } |
944 } | 947 } |
945 | 948 |
946 | 949 |
947 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { | 950 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { |
948 // TODO(rossberg) | 951 // TODO(rossberg) |
949 } | 952 } |
950 | 953 |
951 | 954 |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1414 | 1417 |
1415 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1418 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { |
1416 // Record position before possible IC call. | 1419 // Record position before possible IC call. |
1417 SetSourcePosition(proxy->position()); | 1420 SetSourcePosition(proxy->position()); |
1418 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); | 1421 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); |
1419 Variable* var = proxy->var(); | 1422 Variable* var = proxy->var(); |
1420 | 1423 |
1421 // Three cases: global variables, lookup variables, and all other types of | 1424 // Three cases: global variables, lookup variables, and all other types of |
1422 // variables. | 1425 // variables. |
1423 switch (var->location()) { | 1426 switch (var->location()) { |
1424 case Variable::UNALLOCATED: { | 1427 case VariableLocation::GLOBAL: |
| 1428 case VariableLocation::UNALLOCATED: { |
1425 Comment cmnt(masm_, "[ Global variable"); | 1429 Comment cmnt(masm_, "[ Global variable"); |
1426 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1430 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
1427 __ mov(LoadDescriptor::NameRegister(), var->name()); | 1431 __ mov(LoadDescriptor::NameRegister(), var->name()); |
1428 __ mov(LoadDescriptor::SlotRegister(), | 1432 __ mov(LoadDescriptor::SlotRegister(), |
1429 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); | 1433 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); |
1430 CallGlobalLoadIC(var->name()); | 1434 CallGlobalLoadIC(var->name()); |
1431 context()->Plug(eax); | 1435 context()->Plug(eax); |
1432 break; | 1436 break; |
1433 } | 1437 } |
1434 | 1438 |
1435 case Variable::PARAMETER: | 1439 case VariableLocation::PARAMETER: |
1436 case Variable::LOCAL: | 1440 case VariableLocation::LOCAL: |
1437 case Variable::CONTEXT: { | 1441 case VariableLocation::CONTEXT: { |
1438 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1442 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
1439 : "[ Stack variable"); | 1443 : "[ Stack variable"); |
1440 if (var->binding_needs_init()) { | 1444 if (var->binding_needs_init()) { |
1441 // var->scope() may be NULL when the proxy is located in eval code and | 1445 // var->scope() may be NULL when the proxy is located in eval code and |
1442 // refers to a potential outside binding. Currently those bindings are | 1446 // refers to a potential outside binding. Currently those bindings are |
1443 // always looked up dynamically, i.e. in that case | 1447 // always looked up dynamically, i.e. in that case |
1444 // var->location() == LOOKUP. | 1448 // var->location() == LOOKUP. |
1445 // always holds. | 1449 // always holds. |
1446 DCHECK(var->scope() != NULL); | 1450 DCHECK(var->scope() != NULL); |
1447 | 1451 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1495 } | 1499 } |
1496 __ bind(&done); | 1500 __ bind(&done); |
1497 context()->Plug(eax); | 1501 context()->Plug(eax); |
1498 break; | 1502 break; |
1499 } | 1503 } |
1500 } | 1504 } |
1501 context()->Plug(var); | 1505 context()->Plug(var); |
1502 break; | 1506 break; |
1503 } | 1507 } |
1504 | 1508 |
1505 case Variable::LOOKUP: { | 1509 case VariableLocation::LOOKUP: { |
1506 Comment cmnt(masm_, "[ Lookup variable"); | 1510 Comment cmnt(masm_, "[ Lookup variable"); |
1507 Label done, slow; | 1511 Label done, slow; |
1508 // Generate code for loading from variables potentially shadowed | 1512 // Generate code for loading from variables potentially shadowed |
1509 // by eval-introduced variables. | 1513 // by eval-introduced variables. |
1510 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); | 1514 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); |
1511 __ bind(&slow); | 1515 __ bind(&slow); |
1512 __ push(esi); // Context. | 1516 __ push(esi); // Context. |
1513 __ push(Immediate(var->name())); | 1517 __ push(Immediate(var->name())); |
1514 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 1518 __ CallRuntime(Runtime::kLoadLookupSlot, 2); |
1515 __ bind(&done); | 1519 __ bind(&done); |
(...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2631 if (var->IsContextSlot()) { | 2635 if (var->IsContextSlot()) { |
2632 __ mov(edx, eax); | 2636 __ mov(edx, eax); |
2633 int offset = Context::SlotOffset(var->index()); | 2637 int offset = Context::SlotOffset(var->index()); |
2634 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); | 2638 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); |
2635 } | 2639 } |
2636 } | 2640 } |
2637 | 2641 |
2638 | 2642 |
2639 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 2643 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, |
2640 FeedbackVectorICSlot slot) { | 2644 FeedbackVectorICSlot slot) { |
2641 if (var->IsUnallocated()) { | 2645 if (var->IsUnallocatedOrGlobalSlot()) { |
2642 // Global var, const, or let. | 2646 // Global var, const, or let. |
2643 __ mov(StoreDescriptor::NameRegister(), var->name()); | 2647 __ mov(StoreDescriptor::NameRegister(), var->name()); |
2644 __ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 2648 __ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
2645 if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); | 2649 if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); |
2646 CallStoreIC(); | 2650 CallStoreIC(); |
2647 | 2651 |
2648 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2652 } else if (var->mode() == LET && op != Token::INIT_LET) { |
2649 // Non-initializing assignment to let variable needs a write barrier. | 2653 // Non-initializing assignment to let variable needs a write barrier. |
2650 DCHECK(!var->IsLookupSlot()); | 2654 DCHECK(!var->IsLookupSlot()); |
2651 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2655 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
(...skipping 2076 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4728 VisitForStackValue(property->key()); | 4732 VisitForStackValue(property->key()); |
4729 __ push(Immediate(Smi::FromInt(language_mode()))); | 4733 __ push(Immediate(Smi::FromInt(language_mode()))); |
4730 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4734 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4731 context()->Plug(eax); | 4735 context()->Plug(eax); |
4732 } else if (proxy != NULL) { | 4736 } else if (proxy != NULL) { |
4733 Variable* var = proxy->var(); | 4737 Variable* var = proxy->var(); |
4734 // Delete of an unqualified identifier is disallowed in strict mode but | 4738 // Delete of an unqualified identifier is disallowed in strict mode but |
4735 // "delete this" is allowed. | 4739 // "delete this" is allowed. |
4736 bool is_this = var->HasThisName(isolate()); | 4740 bool is_this = var->HasThisName(isolate()); |
4737 DCHECK(is_sloppy(language_mode()) || is_this); | 4741 DCHECK(is_sloppy(language_mode()) || is_this); |
4738 if (var->IsUnallocated()) { | 4742 if (var->IsUnallocatedOrGlobalSlot()) { |
4739 __ push(GlobalObjectOperand()); | 4743 __ push(GlobalObjectOperand()); |
4740 __ push(Immediate(var->name())); | 4744 __ push(Immediate(var->name())); |
4741 __ push(Immediate(Smi::FromInt(SLOPPY))); | 4745 __ push(Immediate(Smi::FromInt(SLOPPY))); |
4742 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4746 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4743 context()->Plug(eax); | 4747 context()->Plug(eax); |
4744 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4748 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4745 // Result of deleting non-global variables is false. 'this' is | 4749 // Result of deleting non-global variables is false. 'this' is |
4746 // not really a variable, though we implement it as one. The | 4750 // not really a variable, though we implement it as one. The |
4747 // subexpression does not have side effects. | 4751 // subexpression does not have side effects. |
4748 context()->Plug(is_this); | 4752 context()->Plug(is_this); |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5095 } | 5099 } |
5096 } | 5100 } |
5097 } | 5101 } |
5098 | 5102 |
5099 | 5103 |
5100 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 5104 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
5101 VariableProxy* proxy = expr->AsVariableProxy(); | 5105 VariableProxy* proxy = expr->AsVariableProxy(); |
5102 DCHECK(!context()->IsEffect()); | 5106 DCHECK(!context()->IsEffect()); |
5103 DCHECK(!context()->IsTest()); | 5107 DCHECK(!context()->IsTest()); |
5104 | 5108 |
5105 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 5109 if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) { |
5106 Comment cmnt(masm_, "[ Global variable"); | 5110 Comment cmnt(masm_, "[ Global variable"); |
5107 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 5111 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
5108 __ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name())); | 5112 __ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name())); |
5109 __ mov(LoadDescriptor::SlotRegister(), | 5113 __ mov(LoadDescriptor::SlotRegister(), |
5110 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); | 5114 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); |
5111 // Use a regular load, not a contextual load, to avoid a reference | 5115 // Use a regular load, not a contextual load, to avoid a reference |
5112 // error. | 5116 // error. |
5113 CallLoadIC(NOT_CONTEXTUAL); | 5117 CallLoadIC(NOT_CONTEXTUAL); |
5114 PrepareForBailout(expr, TOS_REG); | 5118 PrepareForBailout(expr, TOS_REG); |
5115 context()->Plug(eax); | 5119 context()->Plug(eax); |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5499 Assembler::target_address_at(call_target_address, | 5503 Assembler::target_address_at(call_target_address, |
5500 unoptimized_code)); | 5504 unoptimized_code)); |
5501 return OSR_AFTER_STACK_CHECK; | 5505 return OSR_AFTER_STACK_CHECK; |
5502 } | 5506 } |
5503 | 5507 |
5504 | 5508 |
5505 } // namespace internal | 5509 } // namespace internal |
5506 } // namespace v8 | 5510 } // namespace v8 |
5507 | 5511 |
5508 #endif // V8_TARGET_ARCH_X87 | 5512 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |