| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 } else { | 93 } else { |
| 94 __ CallRuntime(Runtime::kNewContext, 1); | 94 __ CallRuntime(Runtime::kNewContext, 1); |
| 95 } | 95 } |
| 96 function_in_register = false; | 96 function_in_register = false; |
| 97 // Context is returned in both r0 and cp. It replaces the context | 97 // Context is returned in both r0 and cp. It replaces the context |
| 98 // passed to us. It's saved in the stack and kept live in cp. | 98 // passed to us. It's saved in the stack and kept live in cp. |
| 99 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 99 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 100 // Copy any necessary parameters into the context. | 100 // Copy any necessary parameters into the context. |
| 101 int num_parameters = scope()->num_parameters(); | 101 int num_parameters = scope()->num_parameters(); |
| 102 for (int i = 0; i < num_parameters; i++) { | 102 for (int i = 0; i < num_parameters; i++) { |
| 103 Slot* slot = scope()->parameter(i)->slot(); | 103 Slot* slot = scope()->parameter(i)->AsSlot(); |
| 104 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 104 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 105 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 105 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 106 (num_parameters - 1 - i) * kPointerSize; | 106 (num_parameters - 1 - i) * kPointerSize; |
| 107 // Load parameter from stack. | 107 // Load parameter from stack. |
| 108 __ ldr(r0, MemOperand(fp, parameter_offset)); | 108 __ ldr(r0, MemOperand(fp, parameter_offset)); |
| 109 // Store it in the context. | 109 // Store it in the context. |
| 110 __ mov(r1, Operand(Context::SlotOffset(slot->index()))); | 110 __ mov(r1, Operand(Context::SlotOffset(slot->index()))); |
| 111 __ str(r0, MemOperand(cp, r1)); | 111 __ str(r0, MemOperand(cp, r1)); |
| 112 // Update the write barrier. This clobbers all involved | 112 // Update the write barrier. This clobbers all involved |
| 113 // registers, so we have to use two more registers to avoid | 113 // registers, so we have to use two more registers to avoid |
| 114 // clobbering cp. | 114 // clobbering cp. |
| 115 __ mov(r2, Operand(cp)); | 115 __ mov(r2, Operand(cp)); |
| 116 __ RecordWrite(r2, Operand(r1), r3, r0); | 116 __ RecordWrite(r2, Operand(r1), r3, r0); |
| 117 } | 117 } |
| 118 } | 118 } |
| 119 } | 119 } |
| 120 | 120 |
| 121 Variable* arguments = scope()->arguments()->AsVariable(); | 121 Variable* arguments = scope()->arguments(); |
| 122 if (arguments != NULL) { | 122 if (arguments != NULL) { |
| 123 // Function uses arguments object. | 123 // Function uses arguments object. |
| 124 Comment cmnt(masm_, "[ Allocate arguments object"); | 124 Comment cmnt(masm_, "[ Allocate arguments object"); |
| 125 if (!function_in_register) { | 125 if (!function_in_register) { |
| 126 // Load this again, if it's used by the local context below. | 126 // Load this again, if it's used by the local context below. |
| 127 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 127 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 128 } else { | 128 } else { |
| 129 __ mov(r3, r1); | 129 __ mov(r3, r1); |
| 130 } | 130 } |
| 131 // Receiver is just before the parameters on the caller's stack. | 131 // Receiver is just before the parameters on the caller's stack. |
| 132 int offset = scope()->num_parameters() * kPointerSize; | 132 int offset = scope()->num_parameters() * kPointerSize; |
| 133 __ add(r2, fp, | 133 __ add(r2, fp, |
| 134 Operand(StandardFrameConstants::kCallerSPOffset + offset)); | 134 Operand(StandardFrameConstants::kCallerSPOffset + offset)); |
| 135 __ mov(r1, Operand(Smi::FromInt(scope()->num_parameters()))); | 135 __ mov(r1, Operand(Smi::FromInt(scope()->num_parameters()))); |
| 136 __ Push(r3, r2, r1); | 136 __ Push(r3, r2, r1); |
| 137 | 137 |
| 138 // Arguments to ArgumentsAccessStub: | 138 // Arguments to ArgumentsAccessStub: |
| 139 // function, receiver address, parameter count. | 139 // function, receiver address, parameter count. |
| 140 // The stub will rewrite receiever and parameter count if the previous | 140 // The stub will rewrite receiever and parameter count if the previous |
| 141 // stack frame was an arguments adapter frame. | 141 // stack frame was an arguments adapter frame. |
| 142 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | 142 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
| 143 __ CallStub(&stub); | 143 __ CallStub(&stub); |
| 144 // Duplicate the value; move-to-slot operation might clobber registers. | 144 // Duplicate the value; move-to-slot operation might clobber registers. |
| 145 __ mov(r3, r0); | 145 __ mov(r3, r0); |
| 146 Move(arguments->slot(), r0, r1, r2); | 146 Move(arguments->AsSlot(), r0, r1, r2); |
| 147 Slot* dot_arguments_slot = | 147 Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot(); |
| 148 scope()->arguments_shadow()->AsVariable()->slot(); | |
| 149 Move(dot_arguments_slot, r3, r1, r2); | 148 Move(dot_arguments_slot, r3, r1, r2); |
| 150 } | 149 } |
| 151 | 150 |
| 152 { Comment cmnt(masm_, "[ Declarations"); | 151 { Comment cmnt(masm_, "[ Declarations"); |
| 153 // For named function expressions, declare the function name as a | 152 // For named function expressions, declare the function name as a |
| 154 // constant. | 153 // constant. |
| 155 if (scope()->is_function_scope() && scope()->function() != NULL) { | 154 if (scope()->is_function_scope() && scope()->function() != NULL) { |
| 156 EmitDeclaration(scope()->function(), Variable::CONST, NULL); | 155 EmitDeclaration(scope()->function(), Variable::CONST, NULL); |
| 157 } | 156 } |
| 158 // Visit all the explicit declarations unless there is an illegal | 157 // Visit all the explicit declarations unless there is an illegal |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 src); | 522 src); |
| 524 } | 523 } |
| 525 } | 524 } |
| 526 | 525 |
| 527 | 526 |
| 528 void FullCodeGenerator::EmitDeclaration(Variable* variable, | 527 void FullCodeGenerator::EmitDeclaration(Variable* variable, |
| 529 Variable::Mode mode, | 528 Variable::Mode mode, |
| 530 FunctionLiteral* function) { | 529 FunctionLiteral* function) { |
| 531 Comment cmnt(masm_, "[ Declaration"); | 530 Comment cmnt(masm_, "[ Declaration"); |
| 532 ASSERT(variable != NULL); // Must have been resolved. | 531 ASSERT(variable != NULL); // Must have been resolved. |
| 533 Slot* slot = variable->slot(); | 532 Slot* slot = variable->AsSlot(); |
| 534 Property* prop = variable->AsProperty(); | 533 Property* prop = variable->AsProperty(); |
| 535 | 534 |
| 536 if (slot != NULL) { | 535 if (slot != NULL) { |
| 537 switch (slot->type()) { | 536 switch (slot->type()) { |
| 538 case Slot::PARAMETER: | 537 case Slot::PARAMETER: |
| 539 case Slot::LOCAL: | 538 case Slot::LOCAL: |
| 540 if (mode == Variable::CONST) { | 539 if (mode == Variable::CONST) { |
| 541 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 540 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 542 __ str(ip, MemOperand(fp, SlotOffset(slot))); | 541 __ str(ip, MemOperand(fp, SlotOffset(slot))); |
| 543 } else if (function != NULL) { | 542 } else if (function != NULL) { |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 917 Label* done) { | 916 Label* done) { |
| 918 // Generate fast-case code for variables that might be shadowed by | 917 // Generate fast-case code for variables that might be shadowed by |
| 919 // eval-introduced variables. Eval is used a lot without | 918 // eval-introduced variables. Eval is used a lot without |
| 920 // introducing variables. In those cases, we do not want to | 919 // introducing variables. In those cases, we do not want to |
| 921 // perform a runtime call for all variables in the scope | 920 // perform a runtime call for all variables in the scope |
| 922 // containing the eval. | 921 // containing the eval. |
| 923 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 922 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
| 924 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); | 923 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); |
| 925 __ jmp(done); | 924 __ jmp(done); |
| 926 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 925 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
| 927 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | 926 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); |
| 928 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | 927 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); |
| 929 if (potential_slot != NULL) { | 928 if (potential_slot != NULL) { |
| 930 // Generate fast case for locals that rewrite to slots. | 929 // Generate fast case for locals that rewrite to slots. |
| 931 __ ldr(r0, ContextSlotOperandCheckExtensions(potential_slot, slow)); | 930 __ ldr(r0, ContextSlotOperandCheckExtensions(potential_slot, slow)); |
| 932 if (potential_slot->var()->mode() == Variable::CONST) { | 931 if (potential_slot->var()->mode() == Variable::CONST) { |
| 933 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 932 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 934 __ cmp(r0, ip); | 933 __ cmp(r0, ip); |
| 935 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 934 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
| 936 } | 935 } |
| 937 __ jmp(done); | 936 __ jmp(done); |
| 938 } else if (rewrite != NULL) { | 937 } else if (rewrite != NULL) { |
| 939 // Generate fast case for calls of an argument function. | 938 // Generate fast case for calls of an argument function. |
| 940 Property* property = rewrite->AsProperty(); | 939 Property* property = rewrite->AsProperty(); |
| 941 if (property != NULL) { | 940 if (property != NULL) { |
| 942 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | 941 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); |
| 943 Literal* key_literal = property->key()->AsLiteral(); | 942 Literal* key_literal = property->key()->AsLiteral(); |
| 944 if (obj_proxy != NULL && | 943 if (obj_proxy != NULL && |
| 945 key_literal != NULL && | 944 key_literal != NULL && |
| 946 obj_proxy->IsArguments() && | 945 obj_proxy->IsArguments() && |
| 947 key_literal->handle()->IsSmi()) { | 946 key_literal->handle()->IsSmi()) { |
| 948 // Load arguments object if there are no eval-introduced | 947 // Load arguments object if there are no eval-introduced |
| 949 // variables. Then load the argument from the arguments | 948 // variables. Then load the argument from the arguments |
| 950 // object using keyed load. | 949 // object using keyed load. |
| 951 __ ldr(r1, | 950 __ ldr(r1, |
| 952 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | 951 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
| 953 slow)); | 952 slow)); |
| 954 __ mov(r0, Operand(key_literal->handle())); | 953 __ mov(r0, Operand(key_literal->handle())); |
| 955 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 954 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 956 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 955 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 957 __ jmp(done); | 956 __ jmp(done); |
| 958 } | 957 } |
| 959 } | 958 } |
| 960 } | 959 } |
| 961 } | 960 } |
| 962 } | 961 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 : RelocInfo::CODE_TARGET_CONTEXT; | 1019 : RelocInfo::CODE_TARGET_CONTEXT; |
| 1021 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1020 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1022 EmitCallIC(ic, mode); | 1021 EmitCallIC(ic, mode); |
| 1023 } | 1022 } |
| 1024 | 1023 |
| 1025 | 1024 |
| 1026 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1025 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
| 1027 // Four cases: non-this global variables, lookup slots, all other | 1026 // Four cases: non-this global variables, lookup slots, all other |
| 1028 // types of slots, and parameters that rewrite to explicit property | 1027 // types of slots, and parameters that rewrite to explicit property |
| 1029 // accesses on the arguments object. | 1028 // accesses on the arguments object. |
| 1030 Slot* slot = var->slot(); | 1029 Slot* slot = var->AsSlot(); |
| 1031 Property* property = var->AsProperty(); | 1030 Property* property = var->AsProperty(); |
| 1032 | 1031 |
| 1033 if (var->is_global() && !var->is_this()) { | 1032 if (var->is_global() && !var->is_this()) { |
| 1034 Comment cmnt(masm_, "Global variable"); | 1033 Comment cmnt(masm_, "Global variable"); |
| 1035 // Use inline caching. Variable name is passed in r2 and the global | 1034 // Use inline caching. Variable name is passed in r2 and the global |
| 1036 // object (receiver) in r0. | 1035 // object (receiver) in r0. |
| 1037 __ ldr(r0, CodeGenerator::GlobalObject()); | 1036 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 1038 __ mov(r2, Operand(var->name())); | 1037 __ mov(r2, Operand(var->name())); |
| 1039 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1038 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1040 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1039 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1073 context()->Plug(slot); | 1072 context()->Plug(slot); |
| 1074 } | 1073 } |
| 1075 } else { | 1074 } else { |
| 1076 Comment cmnt(masm_, "Rewritten parameter"); | 1075 Comment cmnt(masm_, "Rewritten parameter"); |
| 1077 ASSERT_NOT_NULL(property); | 1076 ASSERT_NOT_NULL(property); |
| 1078 // Rewritten parameter accesses are of the form "slot[literal]". | 1077 // Rewritten parameter accesses are of the form "slot[literal]". |
| 1079 | 1078 |
| 1080 // Assert that the object is in a slot. | 1079 // Assert that the object is in a slot. |
| 1081 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); | 1080 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); |
| 1082 ASSERT_NOT_NULL(object_var); | 1081 ASSERT_NOT_NULL(object_var); |
| 1083 Slot* object_slot = object_var->slot(); | 1082 Slot* object_slot = object_var->AsSlot(); |
| 1084 ASSERT_NOT_NULL(object_slot); | 1083 ASSERT_NOT_NULL(object_slot); |
| 1085 | 1084 |
| 1086 // Load the object. | 1085 // Load the object. |
| 1087 Move(r1, object_slot); | 1086 Move(r1, object_slot); |
| 1088 | 1087 |
| 1089 // Assert that the key is a smi. | 1088 // Assert that the key is a smi. |
| 1090 Literal* key_literal = property->key()->AsLiteral(); | 1089 Literal* key_literal = property->key()->AsLiteral(); |
| 1091 ASSERT_NOT_NULL(key_literal); | 1090 ASSERT_NOT_NULL(key_literal); |
| 1092 ASSERT(key_literal->handle()->IsSmi()); | 1091 ASSERT(key_literal->handle()->IsSmi()); |
| 1093 | 1092 |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1482 } | 1481 } |
| 1483 } | 1482 } |
| 1484 } | 1483 } |
| 1485 | 1484 |
| 1486 | 1485 |
| 1487 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1486 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 1488 Token::Value op) { | 1487 Token::Value op) { |
| 1489 // Left-hand sides that rewrite to explicit property accesses do not reach | 1488 // Left-hand sides that rewrite to explicit property accesses do not reach |
| 1490 // here. | 1489 // here. |
| 1491 ASSERT(var != NULL); | 1490 ASSERT(var != NULL); |
| 1492 ASSERT(var->is_global() || var->slot() != NULL); | 1491 ASSERT(var->is_global() || var->AsSlot() != NULL); |
| 1493 | 1492 |
| 1494 if (var->is_global()) { | 1493 if (var->is_global()) { |
| 1495 ASSERT(!var->is_this()); | 1494 ASSERT(!var->is_this()); |
| 1496 // Assignment to a global variable. Use inline caching for the | 1495 // Assignment to a global variable. Use inline caching for the |
| 1497 // assignment. Right-hand-side value is passed in r0, variable name in | 1496 // assignment. Right-hand-side value is passed in r0, variable name in |
| 1498 // r2, and the global object in r1. | 1497 // r2, and the global object in r1. |
| 1499 __ mov(r2, Operand(var->name())); | 1498 __ mov(r2, Operand(var->name())); |
| 1500 __ ldr(r1, CodeGenerator::GlobalObject()); | 1499 __ ldr(r1, CodeGenerator::GlobalObject()); |
| 1501 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1500 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1502 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1501 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1503 | 1502 |
| 1504 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { | 1503 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { |
| 1505 // Perform the assignment for non-const variables and for initialization | 1504 // Perform the assignment for non-const variables and for initialization |
| 1506 // of const variables. Const assignments are simply skipped. | 1505 // of const variables. Const assignments are simply skipped. |
| 1507 Label done; | 1506 Label done; |
| 1508 Slot* slot = var->slot(); | 1507 Slot* slot = var->AsSlot(); |
| 1509 switch (slot->type()) { | 1508 switch (slot->type()) { |
| 1510 case Slot::PARAMETER: | 1509 case Slot::PARAMETER: |
| 1511 case Slot::LOCAL: | 1510 case Slot::LOCAL: |
| 1512 if (op == Token::INIT_CONST) { | 1511 if (op == Token::INIT_CONST) { |
| 1513 // Detect const reinitialization by checking for the hole value. | 1512 // Detect const reinitialization by checking for the hole value. |
| 1514 __ ldr(r1, MemOperand(fp, SlotOffset(slot))); | 1513 __ ldr(r1, MemOperand(fp, SlotOffset(slot))); |
| 1515 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 1514 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 1516 __ cmp(r1, ip); | 1515 __ cmp(r1, ip); |
| 1517 __ b(ne, &done); | 1516 __ b(ne, &done); |
| 1518 } | 1517 } |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1778 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 1777 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
| 1779 __ CallStub(&stub); | 1778 __ CallStub(&stub); |
| 1780 // Restore context register. | 1779 // Restore context register. |
| 1781 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1780 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1782 context()->DropAndPlug(1, r0); | 1781 context()->DropAndPlug(1, r0); |
| 1783 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1782 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 1784 // Push global object as receiver for the call IC. | 1783 // Push global object as receiver for the call IC. |
| 1785 __ ldr(r0, CodeGenerator::GlobalObject()); | 1784 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 1786 __ push(r0); | 1785 __ push(r0); |
| 1787 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 1786 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
| 1788 } else if (var != NULL && var->slot() != NULL && | 1787 } else if (var != NULL && var->AsSlot() != NULL && |
| 1789 var->slot()->type() == Slot::LOOKUP) { | 1788 var->AsSlot()->type() == Slot::LOOKUP) { |
| 1790 // Call to a lookup slot (dynamically introduced variable). | 1789 // Call to a lookup slot (dynamically introduced variable). |
| 1791 Label slow, done; | 1790 Label slow, done; |
| 1792 | 1791 |
| 1793 // Generate code for loading from variables potentially shadowed | 1792 // Generate code for loading from variables potentially shadowed |
| 1794 // by eval-introduced variables. | 1793 // by eval-introduced variables. |
| 1795 EmitDynamicLoadFromSlotFastCase(var->slot(), | 1794 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
| 1796 NOT_INSIDE_TYPEOF, | 1795 NOT_INSIDE_TYPEOF, |
| 1797 &slow, | 1796 &slow, |
| 1798 &done); | 1797 &done); |
| 1799 | 1798 |
| 1800 __ bind(&slow); | 1799 __ bind(&slow); |
| 1801 // Call the runtime to find the function to call (returned in r0) | 1800 // Call the runtime to find the function to call (returned in r0) |
| 1802 // and the object holding it (returned in edx). | 1801 // and the object holding it (returned in edx). |
| 1803 __ push(context_register()); | 1802 __ push(context_register()); |
| 1804 __ mov(r2, Operand(var->name())); | 1803 __ mov(r2, Operand(var->name())); |
| 1805 __ push(r2); | 1804 __ push(r2); |
| (...skipping 969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2775 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 2774 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 2776 Property* prop = expr->expression()->AsProperty(); | 2775 Property* prop = expr->expression()->AsProperty(); |
| 2777 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 2776 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| 2778 if (prop == NULL && var == NULL) { | 2777 if (prop == NULL && var == NULL) { |
| 2779 // Result of deleting non-property, non-variable reference is true. | 2778 // Result of deleting non-property, non-variable reference is true. |
| 2780 // The subexpression may have side effects. | 2779 // The subexpression may have side effects. |
| 2781 VisitForEffect(expr->expression()); | 2780 VisitForEffect(expr->expression()); |
| 2782 context()->Plug(true); | 2781 context()->Plug(true); |
| 2783 } else if (var != NULL && | 2782 } else if (var != NULL && |
| 2784 !var->is_global() && | 2783 !var->is_global() && |
| 2785 var->slot() != NULL && | 2784 var->AsSlot() != NULL && |
| 2786 var->slot()->type() != Slot::LOOKUP) { | 2785 var->AsSlot()->type() != Slot::LOOKUP) { |
| 2787 // Result of deleting non-global, non-dynamic variables is false. | 2786 // Result of deleting non-global, non-dynamic variables is false. |
| 2788 // The subexpression does not have side effects. | 2787 // The subexpression does not have side effects. |
| 2789 context()->Plug(false); | 2788 context()->Plug(false); |
| 2790 } else { | 2789 } else { |
| 2791 // Property or variable reference. Call the delete builtin with | 2790 // Property or variable reference. Call the delete builtin with |
| 2792 // object and property name as arguments. | 2791 // object and property name as arguments. |
| 2793 if (prop != NULL) { | 2792 if (prop != NULL) { |
| 2794 VisitForStackValue(prop->obj()); | 2793 VisitForStackValue(prop->obj()); |
| 2795 VisitForStackValue(prop->key()); | 2794 VisitForStackValue(prop->key()); |
| 2796 } else if (var->is_global()) { | 2795 } else if (var->is_global()) { |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3061 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 3060 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
| 3062 Comment cmnt(masm_, "Global variable"); | 3061 Comment cmnt(masm_, "Global variable"); |
| 3063 __ ldr(r0, CodeGenerator::GlobalObject()); | 3062 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 3064 __ mov(r2, Operand(proxy->name())); | 3063 __ mov(r2, Operand(proxy->name())); |
| 3065 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 3064 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 3066 // Use a regular load, not a contextual load, to avoid a reference | 3065 // Use a regular load, not a contextual load, to avoid a reference |
| 3067 // error. | 3066 // error. |
| 3068 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3067 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3069 context()->Plug(r0); | 3068 context()->Plug(r0); |
| 3070 } else if (proxy != NULL && | 3069 } else if (proxy != NULL && |
| 3071 proxy->var()->slot() != NULL && | 3070 proxy->var()->AsSlot() != NULL && |
| 3072 proxy->var()->slot()->type() == Slot::LOOKUP) { | 3071 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { |
| 3073 Label done, slow; | 3072 Label done, slow; |
| 3074 | 3073 |
| 3075 // Generate code for loading from variables potentially shadowed | 3074 // Generate code for loading from variables potentially shadowed |
| 3076 // by eval-introduced variables. | 3075 // by eval-introduced variables. |
| 3077 Slot* slot = proxy->var()->slot(); | 3076 Slot* slot = proxy->var()->AsSlot(); |
| 3078 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); | 3077 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); |
| 3079 | 3078 |
| 3080 __ bind(&slow); | 3079 __ bind(&slow); |
| 3081 __ mov(r0, Operand(proxy->name())); | 3080 __ mov(r0, Operand(proxy->name())); |
| 3082 __ Push(cp, r0); | 3081 __ Push(cp, r0); |
| 3083 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 3082 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 3084 __ bind(&done); | 3083 __ bind(&done); |
| 3085 | 3084 |
| 3086 context()->Plug(r0); | 3085 context()->Plug(r0); |
| 3087 } else { | 3086 } else { |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3384 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3383 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 3385 __ add(pc, r1, Operand(masm_->CodeObject())); | 3384 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 3386 } | 3385 } |
| 3387 | 3386 |
| 3388 | 3387 |
| 3389 #undef __ | 3388 #undef __ |
| 3390 | 3389 |
| 3391 } } // namespace v8::internal | 3390 } } // namespace v8::internal |
| 3392 | 3391 |
| 3393 #endif // V8_TARGET_ARCH_ARM | 3392 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |