| 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_ARM | 5 #if V8_TARGET_ARCH_ARM |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 int locals_count = info->scope()->num_stack_slots(); | 137 int locals_count = info->scope()->num_stack_slots(); |
| 138 // Generators allocate locals, if any, in context slots. | 138 // Generators allocate locals, if any, in context slots. |
| 139 DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); | 139 DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); |
| 140 if (locals_count > 0) { | 140 if (locals_count > 0) { |
| 141 if (locals_count >= 128) { | 141 if (locals_count >= 128) { |
| 142 Label ok; | 142 Label ok; |
| 143 __ sub(r9, sp, Operand(locals_count * kPointerSize)); | 143 __ sub(r9, sp, Operand(locals_count * kPointerSize)); |
| 144 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); | 144 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); |
| 145 __ cmp(r9, Operand(r2)); | 145 __ cmp(r9, Operand(r2)); |
| 146 __ b(hs, &ok); | 146 __ b(hs, &ok); |
| 147 __ CallRuntime(Runtime::kThrowStackOverflow, 0); | 147 __ CallRuntime(Runtime::kThrowStackOverflow); |
| 148 __ bind(&ok); | 148 __ bind(&ok); |
| 149 } | 149 } |
| 150 __ LoadRoot(r9, Heap::kUndefinedValueRootIndex); | 150 __ LoadRoot(r9, Heap::kUndefinedValueRootIndex); |
| 151 int kMaxPushes = FLAG_optimize_for_size ? 4 : 32; | 151 int kMaxPushes = FLAG_optimize_for_size ? 4 : 32; |
| 152 if (locals_count >= kMaxPushes) { | 152 if (locals_count >= kMaxPushes) { |
| 153 int loop_iterations = locals_count / kMaxPushes; | 153 int loop_iterations = locals_count / kMaxPushes; |
| 154 __ mov(r2, Operand(loop_iterations)); | 154 __ mov(r2, Operand(loop_iterations)); |
| 155 Label loop_header; | 155 Label loop_header; |
| 156 __ bind(&loop_header); | 156 __ bind(&loop_header); |
| 157 // Do pushes. | 157 // Do pushes. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 174 | 174 |
| 175 // Possibly allocate a local context. | 175 // Possibly allocate a local context. |
| 176 if (info->scope()->num_heap_slots() > 0) { | 176 if (info->scope()->num_heap_slots() > 0) { |
| 177 // Argument to NewContext is the function, which is still in r1. | 177 // Argument to NewContext is the function, which is still in r1. |
| 178 Comment cmnt(masm_, "[ Allocate context"); | 178 Comment cmnt(masm_, "[ Allocate context"); |
| 179 bool need_write_barrier = true; | 179 bool need_write_barrier = true; |
| 180 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 180 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 181 if (info->scope()->is_script_scope()) { | 181 if (info->scope()->is_script_scope()) { |
| 182 __ push(r1); | 182 __ push(r1); |
| 183 __ Push(info->scope()->GetScopeInfo(info->isolate())); | 183 __ Push(info->scope()->GetScopeInfo(info->isolate())); |
| 184 __ CallRuntime(Runtime::kNewScriptContext, 2); | 184 __ CallRuntime(Runtime::kNewScriptContext); |
| 185 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); | 185 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); |
| 186 // The new target value is not used, clobbering is safe. | 186 // The new target value is not used, clobbering is safe. |
| 187 DCHECK_NULL(info->scope()->new_target_var()); | 187 DCHECK_NULL(info->scope()->new_target_var()); |
| 188 } else { | 188 } else { |
| 189 if (info->scope()->new_target_var() != nullptr) { | 189 if (info->scope()->new_target_var() != nullptr) { |
| 190 __ push(r3); // Preserve new target. | 190 __ push(r3); // Preserve new target. |
| 191 } | 191 } |
| 192 if (slots <= FastNewContextStub::kMaximumSlots) { | 192 if (slots <= FastNewContextStub::kMaximumSlots) { |
| 193 FastNewContextStub stub(isolate(), slots); | 193 FastNewContextStub stub(isolate(), slots); |
| 194 __ CallStub(&stub); | 194 __ CallStub(&stub); |
| 195 // Result of FastNewContextStub is always in new space. | 195 // Result of FastNewContextStub is always in new space. |
| 196 need_write_barrier = false; | 196 need_write_barrier = false; |
| 197 } else { | 197 } else { |
| 198 __ push(r1); | 198 __ push(r1); |
| 199 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 199 __ CallRuntime(Runtime::kNewFunctionContext); |
| 200 } | 200 } |
| 201 if (info->scope()->new_target_var() != nullptr) { | 201 if (info->scope()->new_target_var() != nullptr) { |
| 202 __ pop(r3); // Preserve new target. | 202 __ pop(r3); // Preserve new target. |
| 203 } | 203 } |
| 204 } | 204 } |
| 205 function_in_register_r1 = false; | 205 function_in_register_r1 = false; |
| 206 // Context is returned in r0. It replaces the context passed to us. | 206 // Context is returned in r0. It replaces the context passed to us. |
| 207 // It's saved in the stack and kept live in cp. | 207 // It's saved in the stack and kept live in cp. |
| 208 __ mov(cp, r0); | 208 __ mov(cp, r0); |
| 209 __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 209 __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); | 305 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); |
| 306 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( | 306 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( |
| 307 is_unmapped, literal()->has_duplicate_parameters()); | 307 is_unmapped, literal()->has_duplicate_parameters()); |
| 308 ArgumentsAccessStub stub(isolate(), type); | 308 ArgumentsAccessStub stub(isolate(), type); |
| 309 __ CallStub(&stub); | 309 __ CallStub(&stub); |
| 310 | 310 |
| 311 SetVar(arguments, r0, r1, r2); | 311 SetVar(arguments, r0, r1, r2); |
| 312 } | 312 } |
| 313 | 313 |
| 314 if (FLAG_trace) { | 314 if (FLAG_trace) { |
| 315 __ CallRuntime(Runtime::kTraceEnter, 0); | 315 __ CallRuntime(Runtime::kTraceEnter); |
| 316 } | 316 } |
| 317 | 317 |
| 318 // Visit the declarations and body unless there is an illegal | 318 // Visit the declarations and body unless there is an illegal |
| 319 // redeclaration. | 319 // redeclaration. |
| 320 if (scope()->HasIllegalRedeclaration()) { | 320 if (scope()->HasIllegalRedeclaration()) { |
| 321 Comment cmnt(masm_, "[ Declarations"); | 321 Comment cmnt(masm_, "[ Declarations"); |
| 322 VisitForEffect(scope()->GetIllegalRedeclaration()); | 322 VisitForEffect(scope()->GetIllegalRedeclaration()); |
| 323 | 323 |
| 324 } else { | 324 } else { |
| 325 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 325 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 void FullCodeGenerator::EmitReturnSequence() { | 442 void FullCodeGenerator::EmitReturnSequence() { |
| 443 Comment cmnt(masm_, "[ Return sequence"); | 443 Comment cmnt(masm_, "[ Return sequence"); |
| 444 if (return_label_.is_bound()) { | 444 if (return_label_.is_bound()) { |
| 445 __ b(&return_label_); | 445 __ b(&return_label_); |
| 446 } else { | 446 } else { |
| 447 __ bind(&return_label_); | 447 __ bind(&return_label_); |
| 448 if (FLAG_trace) { | 448 if (FLAG_trace) { |
| 449 // Push the return value on the stack as the parameter. | 449 // Push the return value on the stack as the parameter. |
| 450 // Runtime::TraceExit returns its parameter in r0. | 450 // Runtime::TraceExit returns its parameter in r0. |
| 451 __ push(r0); | 451 __ push(r0); |
| 452 __ CallRuntime(Runtime::kTraceExit, 1); | 452 __ CallRuntime(Runtime::kTraceExit); |
| 453 } | 453 } |
| 454 // Pretend that the exit is a backwards jump to the entry. | 454 // Pretend that the exit is a backwards jump to the entry. |
| 455 int weight = 1; | 455 int weight = 1; |
| 456 if (info_->ShouldSelfOptimize()) { | 456 if (info_->ShouldSelfOptimize()) { |
| 457 weight = FLAG_interrupt_budget / FLAG_self_opt_count; | 457 weight = FLAG_interrupt_budget / FLAG_self_opt_count; |
| 458 } else { | 458 } else { |
| 459 int distance = masm_->pc_offset(); | 459 int distance = masm_->pc_offset(); |
| 460 weight = Min(kMaxBackEdgeWeight, | 460 weight = Min(kMaxBackEdgeWeight, |
| 461 Max(1, distance / kCodeSizeMultiplier)); | 461 Max(1, distance / kCodeSizeMultiplier)); |
| 462 } | 462 } |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 // Note: For variables we must not push an initial value (such as | 847 // Note: For variables we must not push an initial value (such as |
| 848 // 'undefined') because we may have a (legal) redeclaration and we | 848 // 'undefined') because we may have a (legal) redeclaration and we |
| 849 // must not destroy the current value. | 849 // must not destroy the current value. |
| 850 if (hole_init) { | 850 if (hole_init) { |
| 851 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 851 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
| 852 } else { | 852 } else { |
| 853 __ mov(r0, Operand(Smi::FromInt(0))); // Indicates no initial value. | 853 __ mov(r0, Operand(Smi::FromInt(0))); // Indicates no initial value. |
| 854 } | 854 } |
| 855 __ Push(r2, r0); | 855 __ Push(r2, r0); |
| 856 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); | 856 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
| 857 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 857 __ CallRuntime(Runtime::kDeclareLookupSlot); |
| 858 break; | 858 break; |
| 859 } | 859 } |
| 860 } | 860 } |
| 861 } | 861 } |
| 862 | 862 |
| 863 | 863 |
| 864 void FullCodeGenerator::VisitFunctionDeclaration( | 864 void FullCodeGenerator::VisitFunctionDeclaration( |
| 865 FunctionDeclaration* declaration) { | 865 FunctionDeclaration* declaration) { |
| 866 VariableProxy* proxy = declaration->proxy(); | 866 VariableProxy* proxy = declaration->proxy(); |
| 867 Variable* variable = proxy->var(); | 867 Variable* variable = proxy->var(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 break; | 904 break; |
| 905 } | 905 } |
| 906 | 906 |
| 907 case VariableLocation::LOOKUP: { | 907 case VariableLocation::LOOKUP: { |
| 908 Comment cmnt(masm_, "[ FunctionDeclaration"); | 908 Comment cmnt(masm_, "[ FunctionDeclaration"); |
| 909 __ mov(r2, Operand(variable->name())); | 909 __ mov(r2, Operand(variable->name())); |
| 910 __ Push(r2); | 910 __ Push(r2); |
| 911 // Push initial value for function declaration. | 911 // Push initial value for function declaration. |
| 912 VisitForStackValue(declaration->fun()); | 912 VisitForStackValue(declaration->fun()); |
| 913 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); | 913 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
| 914 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 914 __ CallRuntime(Runtime::kDeclareLookupSlot); |
| 915 break; | 915 break; |
| 916 } | 916 } |
| 917 } | 917 } |
| 918 } | 918 } |
| 919 | 919 |
| 920 | 920 |
| 921 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 921 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 922 // Call the runtime to declare the globals. | 922 // Call the runtime to declare the globals. |
| 923 __ mov(r1, Operand(pairs)); | 923 __ mov(r1, Operand(pairs)); |
| 924 __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); | 924 __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); |
| 925 __ Push(r1, r0); | 925 __ Push(r1, r0); |
| 926 __ CallRuntime(Runtime::kDeclareGlobals, 2); | 926 __ CallRuntime(Runtime::kDeclareGlobals); |
| 927 // Return value is ignored. | 927 // Return value is ignored. |
| 928 } | 928 } |
| 929 | 929 |
| 930 | 930 |
| 931 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 931 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
| 932 // Call the runtime to declare the modules. | 932 // Call the runtime to declare the modules. |
| 933 __ Push(descriptions); | 933 __ Push(descriptions); |
| 934 __ CallRuntime(Runtime::kDeclareModules, 1); | 934 __ CallRuntime(Runtime::kDeclareModules); |
| 935 // Return value is ignored. | 935 // Return value is ignored. |
| 936 } | 936 } |
| 937 | 937 |
| 938 | 938 |
| 939 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 939 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 940 Comment cmnt(masm_, "[ SwitchStatement"); | 940 Comment cmnt(masm_, "[ SwitchStatement"); |
| 941 Breakable nested_statement(this, stmt); | 941 Breakable nested_statement(this, stmt); |
| 942 SetStatementPosition(stmt); | 942 SetStatementPosition(stmt); |
| 943 | 943 |
| 944 // Keep the switch value on the stack until a case matches. | 944 // Keep the switch value on the stack until a case matches. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1079 | 1079 |
| 1080 // The enum cache is valid. Load the map of the object being | 1080 // The enum cache is valid. Load the map of the object being |
| 1081 // iterated over and use the cache for the iteration. | 1081 // iterated over and use the cache for the iteration. |
| 1082 Label use_cache; | 1082 Label use_cache; |
| 1083 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 1083 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 1084 __ b(&use_cache); | 1084 __ b(&use_cache); |
| 1085 | 1085 |
| 1086 // Get the set of properties to enumerate. | 1086 // Get the set of properties to enumerate. |
| 1087 __ bind(&call_runtime); | 1087 __ bind(&call_runtime); |
| 1088 __ push(r0); // Duplicate the enumerable object on the stack. | 1088 __ push(r0); // Duplicate the enumerable object on the stack. |
| 1089 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 1089 __ CallRuntime(Runtime::kGetPropertyNamesFast); |
| 1090 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); | 1090 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); |
| 1091 | 1091 |
| 1092 // If we got a map from the runtime call, we can do a fast | 1092 // If we got a map from the runtime call, we can do a fast |
| 1093 // modification check. Otherwise, we got a fixed array, and we have | 1093 // modification check. Otherwise, we got a fixed array, and we have |
| 1094 // to do a slow check. | 1094 // to do a slow check. |
| 1095 Label fixed_array; | 1095 Label fixed_array; |
| 1096 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 1096 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 1097 __ LoadRoot(ip, Heap::kMetaMapRootIndex); | 1097 __ LoadRoot(ip, Heap::kMetaMapRootIndex); |
| 1098 __ cmp(r2, ip); | 1098 __ cmp(r2, ip); |
| 1099 __ b(ne, &fixed_array); | 1099 __ b(ne, &fixed_array); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); | 1158 __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); |
| 1159 __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); | 1159 __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 1160 __ cmp(r4, Operand(r2)); | 1160 __ cmp(r4, Operand(r2)); |
| 1161 __ b(eq, &update_each); | 1161 __ b(eq, &update_each); |
| 1162 | 1162 |
| 1163 // Convert the entry to a string or (smi) 0 if it isn't a property | 1163 // Convert the entry to a string or (smi) 0 if it isn't a property |
| 1164 // any more. If the property has been removed while iterating, we | 1164 // any more. If the property has been removed while iterating, we |
| 1165 // just skip it. | 1165 // just skip it. |
| 1166 __ push(r1); // Enumerable. | 1166 __ push(r1); // Enumerable. |
| 1167 __ push(r3); // Current entry. | 1167 __ push(r3); // Current entry. |
| 1168 __ CallRuntime(Runtime::kForInFilter, 2); | 1168 __ CallRuntime(Runtime::kForInFilter); |
| 1169 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); | 1169 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); |
| 1170 __ mov(r3, Operand(r0)); | 1170 __ mov(r3, Operand(r0)); |
| 1171 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1171 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 1172 __ cmp(r0, ip); | 1172 __ cmp(r0, ip); |
| 1173 __ b(eq, loop_statement.continue_label()); | 1173 __ b(eq, loop_statement.continue_label()); |
| 1174 | 1174 |
| 1175 // Update the 'each' property or variable from the possibly filtered | 1175 // Update the 'each' property or variable from the possibly filtered |
| 1176 // entry in register r3. | 1176 // entry in register r3. |
| 1177 __ bind(&update_each); | 1177 __ bind(&update_each); |
| 1178 __ mov(result_register(), r3); | 1178 __ mov(result_register(), r3); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1219 if (!FLAG_always_opt && | 1219 if (!FLAG_always_opt && |
| 1220 !FLAG_prepare_always_opt && | 1220 !FLAG_prepare_always_opt && |
| 1221 !pretenure && | 1221 !pretenure && |
| 1222 scope()->is_function_scope() && | 1222 scope()->is_function_scope() && |
| 1223 info->num_literals() == 0) { | 1223 info->num_literals() == 0) { |
| 1224 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); | 1224 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); |
| 1225 __ mov(r2, Operand(info)); | 1225 __ mov(r2, Operand(info)); |
| 1226 __ CallStub(&stub); | 1226 __ CallStub(&stub); |
| 1227 } else { | 1227 } else { |
| 1228 __ Push(info); | 1228 __ Push(info); |
| 1229 __ CallRuntime( | 1229 __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured |
| 1230 pretenure ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure, 1); | 1230 : Runtime::kNewClosure); |
| 1231 } | 1231 } |
| 1232 context()->Plug(r0); | 1232 context()->Plug(r0); |
| 1233 } | 1233 } |
| 1234 | 1234 |
| 1235 | 1235 |
| 1236 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, | 1236 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, |
| 1237 FeedbackVectorSlot slot) { | 1237 FeedbackVectorSlot slot) { |
| 1238 DCHECK(NeedsHomeObject(initializer)); | 1238 DCHECK(NeedsHomeObject(initializer)); |
| 1239 __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); | 1239 __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); |
| 1240 __ mov(StoreDescriptor::NameRegister(), | 1240 __ mov(StoreDescriptor::NameRegister(), |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1359 __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); | 1359 __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); |
| 1360 if (local->mode() == LET || local->mode() == CONST || | 1360 if (local->mode() == LET || local->mode() == CONST || |
| 1361 local->mode() == CONST_LEGACY) { | 1361 local->mode() == CONST_LEGACY) { |
| 1362 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 1362 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); |
| 1363 if (local->mode() == CONST_LEGACY) { | 1363 if (local->mode() == CONST_LEGACY) { |
| 1364 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 1364 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
| 1365 } else { // LET || CONST | 1365 } else { // LET || CONST |
| 1366 __ b(ne, done); | 1366 __ b(ne, done); |
| 1367 __ mov(r0, Operand(var->name())); | 1367 __ mov(r0, Operand(var->name())); |
| 1368 __ push(r0); | 1368 __ push(r0); |
| 1369 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1369 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1370 } | 1370 } |
| 1371 } | 1371 } |
| 1372 __ jmp(done); | 1372 __ jmp(done); |
| 1373 } | 1373 } |
| 1374 } | 1374 } |
| 1375 | 1375 |
| 1376 | 1376 |
| 1377 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1377 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1378 TypeofMode typeof_mode) { | 1378 TypeofMode typeof_mode) { |
| 1379 Variable* var = proxy->var(); | 1379 Variable* var = proxy->var(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 // Let and const need a read barrier. | 1415 // Let and const need a read barrier. |
| 1416 GetVar(r0, var); | 1416 GetVar(r0, var); |
| 1417 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 1417 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); |
| 1418 if (var->mode() == LET || var->mode() == CONST) { | 1418 if (var->mode() == LET || var->mode() == CONST) { |
| 1419 // Throw a reference error when using an uninitialized let/const | 1419 // Throw a reference error when using an uninitialized let/const |
| 1420 // binding in harmony mode. | 1420 // binding in harmony mode. |
| 1421 Label done; | 1421 Label done; |
| 1422 __ b(ne, &done); | 1422 __ b(ne, &done); |
| 1423 __ mov(r0, Operand(var->name())); | 1423 __ mov(r0, Operand(var->name())); |
| 1424 __ push(r0); | 1424 __ push(r0); |
| 1425 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1425 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1426 __ bind(&done); | 1426 __ bind(&done); |
| 1427 } else { | 1427 } else { |
| 1428 // Uninitialized legacy const bindings are unholed. | 1428 // Uninitialized legacy const bindings are unholed. |
| 1429 DCHECK(var->mode() == CONST_LEGACY); | 1429 DCHECK(var->mode() == CONST_LEGACY); |
| 1430 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 1430 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
| 1431 } | 1431 } |
| 1432 context()->Plug(r0); | 1432 context()->Plug(r0); |
| 1433 break; | 1433 break; |
| 1434 } | 1434 } |
| 1435 context()->Plug(var); | 1435 context()->Plug(var); |
| 1436 break; | 1436 break; |
| 1437 } | 1437 } |
| 1438 | 1438 |
| 1439 case VariableLocation::LOOKUP: { | 1439 case VariableLocation::LOOKUP: { |
| 1440 Comment cmnt(masm_, "[ Lookup variable"); | 1440 Comment cmnt(masm_, "[ Lookup variable"); |
| 1441 Label done, slow; | 1441 Label done, slow; |
| 1442 // Generate code for loading from variables potentially shadowed | 1442 // Generate code for loading from variables potentially shadowed |
| 1443 // by eval-introduced variables. | 1443 // by eval-introduced variables. |
| 1444 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | 1444 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); |
| 1445 __ bind(&slow); | 1445 __ bind(&slow); |
| 1446 __ mov(r1, Operand(var->name())); | 1446 __ mov(r1, Operand(var->name())); |
| 1447 __ Push(cp, r1); // Context and name. | 1447 __ Push(cp, r1); // Context and name. |
| 1448 Runtime::FunctionId function_id = | 1448 Runtime::FunctionId function_id = |
| 1449 typeof_mode == NOT_INSIDE_TYPEOF | 1449 typeof_mode == NOT_INSIDE_TYPEOF |
| 1450 ? Runtime::kLoadLookupSlot | 1450 ? Runtime::kLoadLookupSlot |
| 1451 : Runtime::kLoadLookupSlotNoReferenceError; | 1451 : Runtime::kLoadLookupSlotNoReferenceError; |
| 1452 __ CallRuntime(function_id, 2); | 1452 __ CallRuntime(function_id); |
| 1453 __ bind(&done); | 1453 __ bind(&done); |
| 1454 context()->Plug(r0); | 1454 context()->Plug(r0); |
| 1455 } | 1455 } |
| 1456 } | 1456 } |
| 1457 } | 1457 } |
| 1458 | 1458 |
| 1459 | 1459 |
| 1460 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1460 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1461 Comment cmnt(masm_, "[ RegExpLiteral"); | 1461 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 1462 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1462 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1490 Comment cmnt(masm_, "[ ObjectLiteral"); | 1490 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 1491 | 1491 |
| 1492 Handle<FixedArray> constant_properties = expr->constant_properties(); | 1492 Handle<FixedArray> constant_properties = expr->constant_properties(); |
| 1493 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1493 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1494 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); | 1494 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1495 __ mov(r1, Operand(constant_properties)); | 1495 __ mov(r1, Operand(constant_properties)); |
| 1496 int flags = expr->ComputeFlags(); | 1496 int flags = expr->ComputeFlags(); |
| 1497 __ mov(r0, Operand(Smi::FromInt(flags))); | 1497 __ mov(r0, Operand(Smi::FromInt(flags))); |
| 1498 if (MustCreateObjectLiteralWithRuntime(expr)) { | 1498 if (MustCreateObjectLiteralWithRuntime(expr)) { |
| 1499 __ Push(r3, r2, r1, r0); | 1499 __ Push(r3, r2, r1, r0); |
| 1500 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1500 __ CallRuntime(Runtime::kCreateObjectLiteral); |
| 1501 } else { | 1501 } else { |
| 1502 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1502 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
| 1503 __ CallStub(&stub); | 1503 __ CallStub(&stub); |
| 1504 } | 1504 } |
| 1505 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1505 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
| 1506 | 1506 |
| 1507 // If result_saved is true the result is on top of the stack. If | 1507 // If result_saved is true the result is on top of the stack. If |
| 1508 // result_saved is false the result is in r0. | 1508 // result_saved is false the result is in r0. |
| 1509 bool result_saved = false; | 1509 bool result_saved = false; |
| 1510 | 1510 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1552 __ ldr(r0, MemOperand(sp)); | 1552 __ ldr(r0, MemOperand(sp)); |
| 1553 __ push(r0); | 1553 __ push(r0); |
| 1554 VisitForStackValue(key); | 1554 VisitForStackValue(key); |
| 1555 VisitForStackValue(value); | 1555 VisitForStackValue(value); |
| 1556 if (property->emit_store()) { | 1556 if (property->emit_store()) { |
| 1557 if (NeedsHomeObject(value)) { | 1557 if (NeedsHomeObject(value)) { |
| 1558 EmitSetHomeObject(value, 2, property->GetSlot()); | 1558 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 1559 } | 1559 } |
| 1560 __ mov(r0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes | 1560 __ mov(r0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes |
| 1561 __ push(r0); | 1561 __ push(r0); |
| 1562 __ CallRuntime(Runtime::kSetProperty, 4); | 1562 __ CallRuntime(Runtime::kSetProperty); |
| 1563 } else { | 1563 } else { |
| 1564 __ Drop(3); | 1564 __ Drop(3); |
| 1565 } | 1565 } |
| 1566 break; | 1566 break; |
| 1567 case ObjectLiteral::Property::PROTOTYPE: | 1567 case ObjectLiteral::Property::PROTOTYPE: |
| 1568 // Duplicate receiver on stack. | 1568 // Duplicate receiver on stack. |
| 1569 __ ldr(r0, MemOperand(sp)); | 1569 __ ldr(r0, MemOperand(sp)); |
| 1570 __ push(r0); | 1570 __ push(r0); |
| 1571 VisitForStackValue(value); | 1571 VisitForStackValue(value); |
| 1572 DCHECK(property->emit_store()); | 1572 DCHECK(property->emit_store()); |
| 1573 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1573 __ CallRuntime(Runtime::kInternalSetPrototype); |
| 1574 break; | 1574 break; |
| 1575 | 1575 |
| 1576 case ObjectLiteral::Property::GETTER: | 1576 case ObjectLiteral::Property::GETTER: |
| 1577 if (property->emit_store()) { | 1577 if (property->emit_store()) { |
| 1578 accessor_table.lookup(key)->second->getter = property; | 1578 accessor_table.lookup(key)->second->getter = property; |
| 1579 } | 1579 } |
| 1580 break; | 1580 break; |
| 1581 case ObjectLiteral::Property::SETTER: | 1581 case ObjectLiteral::Property::SETTER: |
| 1582 if (property->emit_store()) { | 1582 if (property->emit_store()) { |
| 1583 accessor_table.lookup(key)->second->setter = property; | 1583 accessor_table.lookup(key)->second->setter = property; |
| 1584 } | 1584 } |
| 1585 break; | 1585 break; |
| 1586 } | 1586 } |
| 1587 } | 1587 } |
| 1588 | 1588 |
| 1589 // Emit code to define accessors, using only a single call to the runtime for | 1589 // Emit code to define accessors, using only a single call to the runtime for |
| 1590 // each pair of corresponding getters and setters. | 1590 // each pair of corresponding getters and setters. |
| 1591 for (AccessorTable::Iterator it = accessor_table.begin(); | 1591 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 1592 it != accessor_table.end(); | 1592 it != accessor_table.end(); |
| 1593 ++it) { | 1593 ++it) { |
| 1594 __ ldr(r0, MemOperand(sp)); // Duplicate receiver. | 1594 __ ldr(r0, MemOperand(sp)); // Duplicate receiver. |
| 1595 __ push(r0); | 1595 __ push(r0); |
| 1596 VisitForStackValue(it->first); | 1596 VisitForStackValue(it->first); |
| 1597 EmitAccessor(it->second->getter); | 1597 EmitAccessor(it->second->getter); |
| 1598 EmitAccessor(it->second->setter); | 1598 EmitAccessor(it->second->setter); |
| 1599 __ mov(r0, Operand(Smi::FromInt(NONE))); | 1599 __ mov(r0, Operand(Smi::FromInt(NONE))); |
| 1600 __ push(r0); | 1600 __ push(r0); |
| 1601 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1601 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); |
| 1602 } | 1602 } |
| 1603 | 1603 |
| 1604 // Object literals have two parts. The "static" part on the left contains no | 1604 // Object literals have two parts. The "static" part on the left contains no |
| 1605 // computed property names, and so we can compute its map ahead of time; see | 1605 // computed property names, and so we can compute its map ahead of time; see |
| 1606 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part | 1606 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
| 1607 // starts with the first computed property name, and continues with all | 1607 // starts with the first computed property name, and continues with all |
| 1608 // properties to its right. All the code from above initializes the static | 1608 // properties to its right. All the code from above initializes the static |
| 1609 // component of the object literal, and arranges for the map of the result to | 1609 // component of the object literal, and arranges for the map of the result to |
| 1610 // reflect the static order in which the keys appear. For the dynamic | 1610 // reflect the static order in which the keys appear. For the dynamic |
| 1611 // properties, we compile them into a series of "SetOwnProperty" runtime | 1611 // properties, we compile them into a series of "SetOwnProperty" runtime |
| 1612 // calls. This will preserve insertion order. | 1612 // calls. This will preserve insertion order. |
| 1613 for (; property_index < expr->properties()->length(); property_index++) { | 1613 for (; property_index < expr->properties()->length(); property_index++) { |
| 1614 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1614 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1615 | 1615 |
| 1616 Expression* value = property->value(); | 1616 Expression* value = property->value(); |
| 1617 if (!result_saved) { | 1617 if (!result_saved) { |
| 1618 __ push(r0); // Save result on the stack | 1618 __ push(r0); // Save result on the stack |
| 1619 result_saved = true; | 1619 result_saved = true; |
| 1620 } | 1620 } |
| 1621 | 1621 |
| 1622 __ ldr(r0, MemOperand(sp)); // Duplicate receiver. | 1622 __ ldr(r0, MemOperand(sp)); // Duplicate receiver. |
| 1623 __ push(r0); | 1623 __ push(r0); |
| 1624 | 1624 |
| 1625 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1625 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
| 1626 DCHECK(!property->is_computed_name()); | 1626 DCHECK(!property->is_computed_name()); |
| 1627 VisitForStackValue(value); | 1627 VisitForStackValue(value); |
| 1628 DCHECK(property->emit_store()); | 1628 DCHECK(property->emit_store()); |
| 1629 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1629 __ CallRuntime(Runtime::kInternalSetPrototype); |
| 1630 } else { | 1630 } else { |
| 1631 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); | 1631 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); |
| 1632 VisitForStackValue(value); | 1632 VisitForStackValue(value); |
| 1633 if (NeedsHomeObject(value)) { | 1633 if (NeedsHomeObject(value)) { |
| 1634 EmitSetHomeObject(value, 2, property->GetSlot()); | 1634 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 1635 } | 1635 } |
| 1636 | 1636 |
| 1637 switch (property->kind()) { | 1637 switch (property->kind()) { |
| 1638 case ObjectLiteral::Property::CONSTANT: | 1638 case ObjectLiteral::Property::CONSTANT: |
| 1639 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1639 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1640 case ObjectLiteral::Property::COMPUTED: | 1640 case ObjectLiteral::Property::COMPUTED: |
| 1641 if (property->emit_store()) { | 1641 if (property->emit_store()) { |
| 1642 __ mov(r0, Operand(Smi::FromInt(NONE))); | 1642 __ mov(r0, Operand(Smi::FromInt(NONE))); |
| 1643 __ push(r0); | 1643 __ push(r0); |
| 1644 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); | 1644 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked); |
| 1645 } else { | 1645 } else { |
| 1646 __ Drop(3); | 1646 __ Drop(3); |
| 1647 } | 1647 } |
| 1648 break; | 1648 break; |
| 1649 | 1649 |
| 1650 case ObjectLiteral::Property::PROTOTYPE: | 1650 case ObjectLiteral::Property::PROTOTYPE: |
| 1651 UNREACHABLE(); | 1651 UNREACHABLE(); |
| 1652 break; | 1652 break; |
| 1653 | 1653 |
| 1654 case ObjectLiteral::Property::GETTER: | 1654 case ObjectLiteral::Property::GETTER: |
| 1655 __ mov(r0, Operand(Smi::FromInt(NONE))); | 1655 __ mov(r0, Operand(Smi::FromInt(NONE))); |
| 1656 __ push(r0); | 1656 __ push(r0); |
| 1657 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 1657 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
| 1658 break; | 1658 break; |
| 1659 | 1659 |
| 1660 case ObjectLiteral::Property::SETTER: | 1660 case ObjectLiteral::Property::SETTER: |
| 1661 __ mov(r0, Operand(Smi::FromInt(NONE))); | 1661 __ mov(r0, Operand(Smi::FromInt(NONE))); |
| 1662 __ push(r0); | 1662 __ push(r0); |
| 1663 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 1663 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
| 1664 break; | 1664 break; |
| 1665 } | 1665 } |
| 1666 } | 1666 } |
| 1667 } | 1667 } |
| 1668 | 1668 |
| 1669 if (expr->has_function()) { | 1669 if (expr->has_function()) { |
| 1670 DCHECK(result_saved); | 1670 DCHECK(result_saved); |
| 1671 __ ldr(r0, MemOperand(sp)); | 1671 __ ldr(r0, MemOperand(sp)); |
| 1672 __ push(r0); | 1672 __ push(r0); |
| 1673 __ CallRuntime(Runtime::kToFastProperties, 1); | 1673 __ CallRuntime(Runtime::kToFastProperties); |
| 1674 } | 1674 } |
| 1675 | 1675 |
| 1676 if (result_saved) { | 1676 if (result_saved) { |
| 1677 context()->PlugTOS(); | 1677 context()->PlugTOS(); |
| 1678 } else { | 1678 } else { |
| 1679 context()->Plug(r0); | 1679 context()->Plug(r0); |
| 1680 } | 1680 } |
| 1681 } | 1681 } |
| 1682 | 1682 |
| 1683 | 1683 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1696 // we can turn it off if we don't have anywhere else to transition to. | 1696 // we can turn it off if we don't have anywhere else to transition to. |
| 1697 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1697 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
| 1698 } | 1698 } |
| 1699 | 1699 |
| 1700 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1700 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1701 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); | 1701 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1702 __ mov(r1, Operand(constant_elements)); | 1702 __ mov(r1, Operand(constant_elements)); |
| 1703 if (MustCreateArrayLiteralWithRuntime(expr)) { | 1703 if (MustCreateArrayLiteralWithRuntime(expr)) { |
| 1704 __ mov(r0, Operand(Smi::FromInt(expr->ComputeFlags()))); | 1704 __ mov(r0, Operand(Smi::FromInt(expr->ComputeFlags()))); |
| 1705 __ Push(r3, r2, r1, r0); | 1705 __ Push(r3, r2, r1, r0); |
| 1706 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); | 1706 __ CallRuntime(Runtime::kCreateArrayLiteral); |
| 1707 } else { | 1707 } else { |
| 1708 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1708 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
| 1709 __ CallStub(&stub); | 1709 __ CallStub(&stub); |
| 1710 } | 1710 } |
| 1711 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1711 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
| 1712 | 1712 |
| 1713 bool result_saved = false; // Is the result saved to the stack? | 1713 bool result_saved = false; // Is the result saved to the stack? |
| 1714 ZoneList<Expression*>* subexprs = expr->values(); | 1714 ZoneList<Expression*>* subexprs = expr->values(); |
| 1715 int length = subexprs->length(); | 1715 int length = subexprs->length(); |
| 1716 | 1716 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1753 for (; array_index < length; array_index++) { | 1753 for (; array_index < length; array_index++) { |
| 1754 Expression* subexpr = subexprs->at(array_index); | 1754 Expression* subexpr = subexprs->at(array_index); |
| 1755 | 1755 |
| 1756 __ Push(r0); | 1756 __ Push(r0); |
| 1757 if (subexpr->IsSpread()) { | 1757 if (subexpr->IsSpread()) { |
| 1758 VisitForStackValue(subexpr->AsSpread()->expression()); | 1758 VisitForStackValue(subexpr->AsSpread()->expression()); |
| 1759 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, | 1759 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, |
| 1760 CALL_FUNCTION); | 1760 CALL_FUNCTION); |
| 1761 } else { | 1761 } else { |
| 1762 VisitForStackValue(subexpr); | 1762 VisitForStackValue(subexpr); |
| 1763 __ CallRuntime(Runtime::kAppendElement, 2); | 1763 __ CallRuntime(Runtime::kAppendElement); |
| 1764 } | 1764 } |
| 1765 | 1765 |
| 1766 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); | 1766 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
| 1767 } | 1767 } |
| 1768 | 1768 |
| 1769 if (result_saved) { | 1769 if (result_saved) { |
| 1770 context()->PlugTOS(); | 1770 context()->PlugTOS(); |
| 1771 } else { | 1771 } else { |
| 1772 context()->Plug(r0); | 1772 context()->Plug(r0); |
| 1773 } | 1773 } |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2165 Label push_operand_holes, call_resume; | 2165 Label push_operand_holes, call_resume; |
| 2166 __ bind(&push_operand_holes); | 2166 __ bind(&push_operand_holes); |
| 2167 __ sub(r3, r3, Operand(1), SetCC); | 2167 __ sub(r3, r3, Operand(1), SetCC); |
| 2168 __ b(mi, &call_resume); | 2168 __ b(mi, &call_resume); |
| 2169 __ push(r2); | 2169 __ push(r2); |
| 2170 __ b(&push_operand_holes); | 2170 __ b(&push_operand_holes); |
| 2171 __ bind(&call_resume); | 2171 __ bind(&call_resume); |
| 2172 DCHECK(!result_register().is(r1)); | 2172 DCHECK(!result_register().is(r1)); |
| 2173 __ Push(r1, result_register()); | 2173 __ Push(r1, result_register()); |
| 2174 __ Push(Smi::FromInt(resume_mode)); | 2174 __ Push(Smi::FromInt(resume_mode)); |
| 2175 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2175 __ CallRuntime(Runtime::kResumeJSGeneratorObject); |
| 2176 // Not reached: the runtime call returns elsewhere. | 2176 // Not reached: the runtime call returns elsewhere. |
| 2177 __ stop("not-reached"); | 2177 __ stop("not-reached"); |
| 2178 | 2178 |
| 2179 __ bind(&done); | 2179 __ bind(&done); |
| 2180 context()->Plug(result_register()); | 2180 context()->Plug(result_register()); |
| 2181 } | 2181 } |
| 2182 | 2182 |
| 2183 | 2183 |
| 2184 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2184 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| 2185 Label allocate, done_allocate; | 2185 Label allocate, done_allocate; |
| 2186 | 2186 |
| 2187 __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &allocate, TAG_OBJECT); | 2187 __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &allocate, TAG_OBJECT); |
| 2188 __ b(&done_allocate); | 2188 __ b(&done_allocate); |
| 2189 | 2189 |
| 2190 __ bind(&allocate); | 2190 __ bind(&allocate); |
| 2191 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 2191 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
| 2192 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2192 __ CallRuntime(Runtime::kAllocateInNewSpace); |
| 2193 | 2193 |
| 2194 __ bind(&done_allocate); | 2194 __ bind(&done_allocate); |
| 2195 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r1); | 2195 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r1); |
| 2196 __ pop(r2); | 2196 __ pop(r2); |
| 2197 __ LoadRoot(r3, | 2197 __ LoadRoot(r3, |
| 2198 done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); | 2198 done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); |
| 2199 __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); | 2199 __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); |
| 2200 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 2200 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 2201 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | 2201 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); |
| 2202 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); | 2202 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2219 | 2219 |
| 2220 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { | 2220 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
| 2221 // Stack: receiver, home_object. | 2221 // Stack: receiver, home_object. |
| 2222 SetExpressionPosition(prop); | 2222 SetExpressionPosition(prop); |
| 2223 Literal* key = prop->key()->AsLiteral(); | 2223 Literal* key = prop->key()->AsLiteral(); |
| 2224 DCHECK(!key->value()->IsSmi()); | 2224 DCHECK(!key->value()->IsSmi()); |
| 2225 DCHECK(prop->IsSuperAccess()); | 2225 DCHECK(prop->IsSuperAccess()); |
| 2226 | 2226 |
| 2227 __ Push(key->value()); | 2227 __ Push(key->value()); |
| 2228 __ Push(Smi::FromInt(language_mode())); | 2228 __ Push(Smi::FromInt(language_mode())); |
| 2229 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2229 __ CallRuntime(Runtime::kLoadFromSuper); |
| 2230 } | 2230 } |
| 2231 | 2231 |
| 2232 | 2232 |
| 2233 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2233 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2234 SetExpressionPosition(prop); | 2234 SetExpressionPosition(prop); |
| 2235 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); | 2235 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); |
| 2236 __ mov(LoadDescriptor::SlotRegister(), | 2236 __ mov(LoadDescriptor::SlotRegister(), |
| 2237 Operand(SmiFromSlot(prop->PropertyFeedbackSlot()))); | 2237 Operand(SmiFromSlot(prop->PropertyFeedbackSlot()))); |
| 2238 CallIC(ic); | 2238 CallIC(ic); |
| 2239 } | 2239 } |
| 2240 | 2240 |
| 2241 | 2241 |
| 2242 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { | 2242 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
| 2243 // Stack: receiver, home_object, key. | 2243 // Stack: receiver, home_object, key. |
| 2244 SetExpressionPosition(prop); | 2244 SetExpressionPosition(prop); |
| 2245 __ Push(Smi::FromInt(language_mode())); | 2245 __ Push(Smi::FromInt(language_mode())); |
| 2246 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2246 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
| 2247 } | 2247 } |
| 2248 | 2248 |
| 2249 | 2249 |
| 2250 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2250 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2251 Token::Value op, | 2251 Token::Value op, |
| 2252 Expression* left_expr, | 2252 Expression* left_expr, |
| 2253 Expression* right_expr) { | 2253 Expression* right_expr) { |
| 2254 Label done, smi_case, stub_call; | 2254 Label done, smi_case, stub_call; |
| 2255 | 2255 |
| 2256 Register scratch1 = r2; | 2256 Register scratch1 = r2; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2363 __ ldr(scratch, MemOperand(sp, 0)); // prototype | 2363 __ ldr(scratch, MemOperand(sp, 0)); // prototype |
| 2364 } | 2364 } |
| 2365 __ push(scratch); | 2365 __ push(scratch); |
| 2366 EmitPropertyKey(property, lit->GetIdForProperty(i)); | 2366 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
| 2367 | 2367 |
| 2368 // The static prototype property is read only. We handle the non computed | 2368 // The static prototype property is read only. We handle the non computed |
| 2369 // property name case in the parser. Since this is the only case where we | 2369 // property name case in the parser. Since this is the only case where we |
| 2370 // need to check for an own read only property we special case this so we do | 2370 // need to check for an own read only property we special case this so we do |
| 2371 // not need to do this for every property. | 2371 // not need to do this for every property. |
| 2372 if (property->is_static() && property->is_computed_name()) { | 2372 if (property->is_static() && property->is_computed_name()) { |
| 2373 __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1); | 2373 __ CallRuntime(Runtime::kThrowIfStaticPrototype); |
| 2374 __ push(r0); | 2374 __ push(r0); |
| 2375 } | 2375 } |
| 2376 | 2376 |
| 2377 VisitForStackValue(value); | 2377 VisitForStackValue(value); |
| 2378 if (NeedsHomeObject(value)) { | 2378 if (NeedsHomeObject(value)) { |
| 2379 EmitSetHomeObject(value, 2, property->GetSlot()); | 2379 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 2380 } | 2380 } |
| 2381 | 2381 |
| 2382 switch (property->kind()) { | 2382 switch (property->kind()) { |
| 2383 case ObjectLiteral::Property::CONSTANT: | 2383 case ObjectLiteral::Property::CONSTANT: |
| 2384 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2384 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 2385 case ObjectLiteral::Property::PROTOTYPE: | 2385 case ObjectLiteral::Property::PROTOTYPE: |
| 2386 UNREACHABLE(); | 2386 UNREACHABLE(); |
| 2387 case ObjectLiteral::Property::COMPUTED: | 2387 case ObjectLiteral::Property::COMPUTED: |
| 2388 __ CallRuntime(Runtime::kDefineClassMethod, 3); | 2388 __ CallRuntime(Runtime::kDefineClassMethod); |
| 2389 break; | 2389 break; |
| 2390 | 2390 |
| 2391 case ObjectLiteral::Property::GETTER: | 2391 case ObjectLiteral::Property::GETTER: |
| 2392 __ mov(r0, Operand(Smi::FromInt(DONT_ENUM))); | 2392 __ mov(r0, Operand(Smi::FromInt(DONT_ENUM))); |
| 2393 __ push(r0); | 2393 __ push(r0); |
| 2394 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 2394 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
| 2395 break; | 2395 break; |
| 2396 | 2396 |
| 2397 case ObjectLiteral::Property::SETTER: | 2397 case ObjectLiteral::Property::SETTER: |
| 2398 __ mov(r0, Operand(Smi::FromInt(DONT_ENUM))); | 2398 __ mov(r0, Operand(Smi::FromInt(DONT_ENUM))); |
| 2399 __ push(r0); | 2399 __ push(r0); |
| 2400 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 2400 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
| 2401 break; | 2401 break; |
| 2402 | 2402 |
| 2403 default: | 2403 default: |
| 2404 UNREACHABLE(); | 2404 UNREACHABLE(); |
| 2405 } | 2405 } |
| 2406 } | 2406 } |
| 2407 | 2407 |
| 2408 // Set both the prototype and constructor to have fast properties, and also | 2408 // Set both the prototype and constructor to have fast properties, and also |
| 2409 // freeze them in strong mode. | 2409 // freeze them in strong mode. |
| 2410 __ CallRuntime(Runtime::kFinalizeClassDefinition, 2); | 2410 __ CallRuntime(Runtime::kFinalizeClassDefinition); |
| 2411 } | 2411 } |
| 2412 | 2412 |
| 2413 | 2413 |
| 2414 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { | 2414 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
| 2415 __ pop(r1); | 2415 __ pop(r1); |
| 2416 Handle<Code> code = | 2416 Handle<Code> code = |
| 2417 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); | 2417 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); |
| 2418 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2418 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2419 CallIC(code, expr->BinaryOperationFeedbackId()); | 2419 CallIC(code, expr->BinaryOperationFeedbackId()); |
| 2420 patch_site.EmitPatchInfo(); | 2420 patch_site.EmitPatchInfo(); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2528 // Non-initializing assignment to let variable needs a write barrier. | 2528 // Non-initializing assignment to let variable needs a write barrier. |
| 2529 DCHECK(!var->IsLookupSlot()); | 2529 DCHECK(!var->IsLookupSlot()); |
| 2530 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2530 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2531 Label assign; | 2531 Label assign; |
| 2532 MemOperand location = VarOperand(var, r1); | 2532 MemOperand location = VarOperand(var, r1); |
| 2533 __ ldr(r3, location); | 2533 __ ldr(r3, location); |
| 2534 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 2534 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 2535 __ b(ne, &assign); | 2535 __ b(ne, &assign); |
| 2536 __ mov(r3, Operand(var->name())); | 2536 __ mov(r3, Operand(var->name())); |
| 2537 __ push(r3); | 2537 __ push(r3); |
| 2538 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2538 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2539 // Perform the assignment. | 2539 // Perform the assignment. |
| 2540 __ bind(&assign); | 2540 __ bind(&assign); |
| 2541 EmitStoreToStackLocalOrContextSlot(var, location); | 2541 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2542 | 2542 |
| 2543 } else if (var->mode() == CONST && op != Token::INIT) { | 2543 } else if (var->mode() == CONST && op != Token::INIT) { |
| 2544 // Assignment to const variable needs a write barrier. | 2544 // Assignment to const variable needs a write barrier. |
| 2545 DCHECK(!var->IsLookupSlot()); | 2545 DCHECK(!var->IsLookupSlot()); |
| 2546 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2546 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2547 Label const_error; | 2547 Label const_error; |
| 2548 MemOperand location = VarOperand(var, r1); | 2548 MemOperand location = VarOperand(var, r1); |
| 2549 __ ldr(r3, location); | 2549 __ ldr(r3, location); |
| 2550 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 2550 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 2551 __ b(ne, &const_error); | 2551 __ b(ne, &const_error); |
| 2552 __ mov(r3, Operand(var->name())); | 2552 __ mov(r3, Operand(var->name())); |
| 2553 __ push(r3); | 2553 __ push(r3); |
| 2554 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2554 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2555 __ bind(&const_error); | 2555 __ bind(&const_error); |
| 2556 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2556 __ CallRuntime(Runtime::kThrowConstAssignError); |
| 2557 | 2557 |
| 2558 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | 2558 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
| 2559 // Initializing assignment to const {this} needs a write barrier. | 2559 // Initializing assignment to const {this} needs a write barrier. |
| 2560 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2560 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2561 Label uninitialized_this; | 2561 Label uninitialized_this; |
| 2562 MemOperand location = VarOperand(var, r1); | 2562 MemOperand location = VarOperand(var, r1); |
| 2563 __ ldr(r3, location); | 2563 __ ldr(r3, location); |
| 2564 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 2564 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 2565 __ b(eq, &uninitialized_this); | 2565 __ b(eq, &uninitialized_this); |
| 2566 __ mov(r0, Operand(var->name())); | 2566 __ mov(r0, Operand(var->name())); |
| 2567 __ Push(r0); | 2567 __ Push(r0); |
| 2568 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2568 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2569 __ bind(&uninitialized_this); | 2569 __ bind(&uninitialized_this); |
| 2570 EmitStoreToStackLocalOrContextSlot(var, location); | 2570 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2571 | 2571 |
| 2572 } else if (!var->is_const_mode() || | 2572 } else if (!var->is_const_mode() || |
| 2573 (var->mode() == CONST && op == Token::INIT)) { | 2573 (var->mode() == CONST && op == Token::INIT)) { |
| 2574 if (var->IsLookupSlot()) { | 2574 if (var->IsLookupSlot()) { |
| 2575 // Assignment to var. | 2575 // Assignment to var. |
| 2576 __ push(r0); // Value. | 2576 __ push(r0); // Value. |
| 2577 __ mov(r1, Operand(var->name())); | 2577 __ mov(r1, Operand(var->name())); |
| 2578 __ mov(r0, Operand(Smi::FromInt(language_mode()))); | 2578 __ mov(r0, Operand(Smi::FromInt(language_mode()))); |
| 2579 __ Push(cp, r1, r0); // Context, name, language mode. | 2579 __ Push(cp, r1, r0); // Context, name, language mode. |
| 2580 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2580 __ CallRuntime(Runtime::kStoreLookupSlot); |
| 2581 } else { | 2581 } else { |
| 2582 // Assignment to var or initializing assignment to let/const in harmony | 2582 // Assignment to var or initializing assignment to let/const in harmony |
| 2583 // mode. | 2583 // mode. |
| 2584 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 2584 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
| 2585 MemOperand location = VarOperand(var, r1); | 2585 MemOperand location = VarOperand(var, r1); |
| 2586 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { | 2586 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { |
| 2587 // Check for an uninitialized let binding. | 2587 // Check for an uninitialized let binding. |
| 2588 __ ldr(r2, location); | 2588 __ ldr(r2, location); |
| 2589 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 2589 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); |
| 2590 __ Check(eq, kLetBindingReInitialization); | 2590 __ Check(eq, kLetBindingReInitialization); |
| 2591 } | 2591 } |
| 2592 EmitStoreToStackLocalOrContextSlot(var, location); | 2592 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2593 } | 2593 } |
| 2594 | 2594 |
| 2595 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { | 2595 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { |
| 2596 // Const initializers need a write barrier. | 2596 // Const initializers need a write barrier. |
| 2597 DCHECK(!var->IsParameter()); // No const parameters. | 2597 DCHECK(!var->IsParameter()); // No const parameters. |
| 2598 if (var->IsLookupSlot()) { | 2598 if (var->IsLookupSlot()) { |
| 2599 __ push(r0); | 2599 __ push(r0); |
| 2600 __ mov(r0, Operand(var->name())); | 2600 __ mov(r0, Operand(var->name())); |
| 2601 __ Push(cp, r0); // Context and name. | 2601 __ Push(cp, r0); // Context and name. |
| 2602 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2602 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot); |
| 2603 } else { | 2603 } else { |
| 2604 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2604 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2605 Label skip; | 2605 Label skip; |
| 2606 MemOperand location = VarOperand(var, r1); | 2606 MemOperand location = VarOperand(var, r1); |
| 2607 __ ldr(r2, location); | 2607 __ ldr(r2, location); |
| 2608 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 2608 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); |
| 2609 __ b(ne, &skip); | 2609 __ b(ne, &skip); |
| 2610 EmitStoreToStackLocalOrContextSlot(var, location); | 2610 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2611 __ bind(&skip); | 2611 __ bind(&skip); |
| 2612 } | 2612 } |
| 2613 | 2613 |
| 2614 } else { | 2614 } else { |
| 2615 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); | 2615 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); |
| 2616 if (is_strict(language_mode())) { | 2616 if (is_strict(language_mode())) { |
| 2617 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2617 __ CallRuntime(Runtime::kThrowConstAssignError); |
| 2618 } | 2618 } |
| 2619 // Silently ignore store in sloppy mode. | 2619 // Silently ignore store in sloppy mode. |
| 2620 } | 2620 } |
| 2621 } | 2621 } |
| 2622 | 2622 |
| 2623 | 2623 |
| 2624 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2624 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2625 // Assignment to a property, using a named store IC. | 2625 // Assignment to a property, using a named store IC. |
| 2626 Property* prop = expr->target()->AsProperty(); | 2626 Property* prop = expr->target()->AsProperty(); |
| 2627 DCHECK(prop != NULL); | 2627 DCHECK(prop != NULL); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2642 // Assignment to named property of super. | 2642 // Assignment to named property of super. |
| 2643 // r0 : value | 2643 // r0 : value |
| 2644 // stack : receiver ('this'), home_object | 2644 // stack : receiver ('this'), home_object |
| 2645 DCHECK(prop != NULL); | 2645 DCHECK(prop != NULL); |
| 2646 Literal* key = prop->key()->AsLiteral(); | 2646 Literal* key = prop->key()->AsLiteral(); |
| 2647 DCHECK(key != NULL); | 2647 DCHECK(key != NULL); |
| 2648 | 2648 |
| 2649 __ Push(key->value()); | 2649 __ Push(key->value()); |
| 2650 __ Push(r0); | 2650 __ Push(r0); |
| 2651 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict | 2651 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
| 2652 : Runtime::kStoreToSuper_Sloppy), | 2652 : Runtime::kStoreToSuper_Sloppy)); |
| 2653 4); | |
| 2654 } | 2653 } |
| 2655 | 2654 |
| 2656 | 2655 |
| 2657 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { | 2656 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
| 2658 // Assignment to named property of super. | 2657 // Assignment to named property of super. |
| 2659 // r0 : value | 2658 // r0 : value |
| 2660 // stack : receiver ('this'), home_object, key | 2659 // stack : receiver ('this'), home_object, key |
| 2661 DCHECK(prop != NULL); | 2660 DCHECK(prop != NULL); |
| 2662 | 2661 |
| 2663 __ Push(r0); | 2662 __ Push(r0); |
| 2664 __ CallRuntime( | 2663 __ CallRuntime((is_strict(language_mode()) |
| 2665 (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 2664 ? Runtime::kStoreKeyedToSuper_Strict |
| 2666 : Runtime::kStoreKeyedToSuper_Sloppy), | 2665 : Runtime::kStoreKeyedToSuper_Sloppy)); |
| 2667 4); | |
| 2668 } | 2666 } |
| 2669 | 2667 |
| 2670 | 2668 |
| 2671 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2669 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2672 // Assignment to a property, using a keyed store IC. | 2670 // Assignment to a property, using a keyed store IC. |
| 2673 __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); | 2671 __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); |
| 2674 DCHECK(StoreDescriptor::ValueRegister().is(r0)); | 2672 DCHECK(StoreDescriptor::ValueRegister().is(r0)); |
| 2675 | 2673 |
| 2676 Handle<Code> ic = | 2674 Handle<Code> ic = |
| 2677 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); | 2675 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2785 __ Push(key->value()); | 2783 __ Push(key->value()); |
| 2786 __ Push(Smi::FromInt(language_mode())); | 2784 __ Push(Smi::FromInt(language_mode())); |
| 2787 | 2785 |
| 2788 // Stack here: | 2786 // Stack here: |
| 2789 // - home_object | 2787 // - home_object |
| 2790 // - this (receiver) | 2788 // - this (receiver) |
| 2791 // - this (receiver) <-- LoadFromSuper will pop here and below. | 2789 // - this (receiver) <-- LoadFromSuper will pop here and below. |
| 2792 // - home_object | 2790 // - home_object |
| 2793 // - key | 2791 // - key |
| 2794 // - language_mode | 2792 // - language_mode |
| 2795 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2793 __ CallRuntime(Runtime::kLoadFromSuper); |
| 2796 | 2794 |
| 2797 // Replace home_object with target function. | 2795 // Replace home_object with target function. |
| 2798 __ str(r0, MemOperand(sp, kPointerSize)); | 2796 __ str(r0, MemOperand(sp, kPointerSize)); |
| 2799 | 2797 |
| 2800 // Stack here: | 2798 // Stack here: |
| 2801 // - target function | 2799 // - target function |
| 2802 // - this (receiver) | 2800 // - this (receiver) |
| 2803 EmitCall(expr); | 2801 EmitCall(expr); |
| 2804 } | 2802 } |
| 2805 | 2803 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2847 VisitForStackValue(prop->key()); | 2845 VisitForStackValue(prop->key()); |
| 2848 __ Push(Smi::FromInt(language_mode())); | 2846 __ Push(Smi::FromInt(language_mode())); |
| 2849 | 2847 |
| 2850 // Stack here: | 2848 // Stack here: |
| 2851 // - home_object | 2849 // - home_object |
| 2852 // - this (receiver) | 2850 // - this (receiver) |
| 2853 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. | 2851 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. |
| 2854 // - home_object | 2852 // - home_object |
| 2855 // - key | 2853 // - key |
| 2856 // - language_mode | 2854 // - language_mode |
| 2857 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2855 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
| 2858 | 2856 |
| 2859 // Replace home_object with target function. | 2857 // Replace home_object with target function. |
| 2860 __ str(r0, MemOperand(sp, kPointerSize)); | 2858 __ str(r0, MemOperand(sp, kPointerSize)); |
| 2861 | 2859 |
| 2862 // Stack here: | 2860 // Stack here: |
| 2863 // - target function | 2861 // - target function |
| 2864 // - this (receiver) | 2862 // - this (receiver) |
| 2865 EmitCall(expr); | 2863 EmitCall(expr); |
| 2866 } | 2864 } |
| 2867 | 2865 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2902 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 2900 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 2903 | 2901 |
| 2904 // r2: language mode. | 2902 // r2: language mode. |
| 2905 __ mov(r2, Operand(Smi::FromInt(language_mode()))); | 2903 __ mov(r2, Operand(Smi::FromInt(language_mode()))); |
| 2906 | 2904 |
| 2907 // r1: the start position of the scope the calls resides in. | 2905 // r1: the start position of the scope the calls resides in. |
| 2908 __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); | 2906 __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); |
| 2909 | 2907 |
| 2910 // Do the runtime call. | 2908 // Do the runtime call. |
| 2911 __ Push(r4, r3, r2, r1); | 2909 __ Push(r4, r3, r2, r1); |
| 2912 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2910 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); |
| 2913 } | 2911 } |
| 2914 | 2912 |
| 2915 | 2913 |
| 2916 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | 2914 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. |
| 2917 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | 2915 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
| 2918 VariableProxy* callee = expr->expression()->AsVariableProxy(); | 2916 VariableProxy* callee = expr->expression()->AsVariableProxy(); |
| 2919 if (callee->var()->IsLookupSlot()) { | 2917 if (callee->var()->IsLookupSlot()) { |
| 2920 Label slow, done; | 2918 Label slow, done; |
| 2921 SetExpressionPosition(callee); | 2919 SetExpressionPosition(callee); |
| 2922 // Generate code for loading from variables potentially shadowed | 2920 // Generate code for loading from variables potentially shadowed |
| 2923 // by eval-introduced variables. | 2921 // by eval-introduced variables. |
| 2924 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | 2922 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |
| 2925 | 2923 |
| 2926 __ bind(&slow); | 2924 __ bind(&slow); |
| 2927 // Call the runtime to find the function to call (returned in r0) | 2925 // Call the runtime to find the function to call (returned in r0) |
| 2928 // and the object holding it (returned in edx). | 2926 // and the object holding it (returned in edx). |
| 2929 DCHECK(!context_register().is(r2)); | 2927 DCHECK(!context_register().is(r2)); |
| 2930 __ mov(r2, Operand(callee->name())); | 2928 __ mov(r2, Operand(callee->name())); |
| 2931 __ Push(context_register(), r2); | 2929 __ Push(context_register(), r2); |
| 2932 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 2930 __ CallRuntime(Runtime::kLoadLookupSlot); |
| 2933 __ Push(r0, r1); // Function, receiver. | 2931 __ Push(r0, r1); // Function, receiver. |
| 2934 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); | 2932 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
| 2935 | 2933 |
| 2936 // If fast case code has been generated, emit code to push the | 2934 // If fast case code has been generated, emit code to push the |
| 2937 // function and receiver and have the slow path jump around this | 2935 // function and receiver and have the slow path jump around this |
| 2938 // code. | 2936 // code. |
| 2939 if (done.is_linked()) { | 2937 if (done.is_linked()) { |
| 2940 Label call; | 2938 Label call; |
| 2941 __ b(&call); | 2939 __ b(&call); |
| 2942 __ bind(&done); | 2940 __ bind(&done); |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3565 ZoneList<Expression*>* args = expr->arguments(); | 3563 ZoneList<Expression*>* args = expr->arguments(); |
| 3566 DCHECK_EQ(1, args->length()); | 3564 DCHECK_EQ(1, args->length()); |
| 3567 | 3565 |
| 3568 // Load the argument into r0 and convert it. | 3566 // Load the argument into r0 and convert it. |
| 3569 VisitForAccumulatorValue(args->at(0)); | 3567 VisitForAccumulatorValue(args->at(0)); |
| 3570 | 3568 |
| 3571 // Convert the object to an integer. | 3569 // Convert the object to an integer. |
| 3572 Label done_convert; | 3570 Label done_convert; |
| 3573 __ JumpIfSmi(r0, &done_convert); | 3571 __ JumpIfSmi(r0, &done_convert); |
| 3574 __ Push(r0); | 3572 __ Push(r0); |
| 3575 __ CallRuntime(Runtime::kToInteger, 1); | 3573 __ CallRuntime(Runtime::kToInteger); |
| 3576 __ bind(&done_convert); | 3574 __ bind(&done_convert); |
| 3577 context()->Plug(r0); | 3575 context()->Plug(r0); |
| 3578 } | 3576 } |
| 3579 | 3577 |
| 3580 | 3578 |
| 3581 void FullCodeGenerator::EmitToName(CallRuntime* expr) { | 3579 void FullCodeGenerator::EmitToName(CallRuntime* expr) { |
| 3582 ZoneList<Expression*>* args = expr->arguments(); | 3580 ZoneList<Expression*>* args = expr->arguments(); |
| 3583 DCHECK_EQ(1, args->length()); | 3581 DCHECK_EQ(1, args->length()); |
| 3584 | 3582 |
| 3585 // Load the argument into r0 and convert it. | 3583 // Load the argument into r0 and convert it. |
| 3586 VisitForAccumulatorValue(args->at(0)); | 3584 VisitForAccumulatorValue(args->at(0)); |
| 3587 | 3585 |
| 3588 Label convert, done_convert; | 3586 Label convert, done_convert; |
| 3589 __ JumpIfSmi(r0, &convert); | 3587 __ JumpIfSmi(r0, &convert); |
| 3590 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); | 3588 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); |
| 3591 __ CompareObjectType(r0, r1, r1, LAST_NAME_TYPE); | 3589 __ CompareObjectType(r0, r1, r1, LAST_NAME_TYPE); |
| 3592 __ b(ls, &done_convert); | 3590 __ b(ls, &done_convert); |
| 3593 __ bind(&convert); | 3591 __ bind(&convert); |
| 3594 __ Push(r0); | 3592 __ Push(r0); |
| 3595 __ CallRuntime(Runtime::kToName, 1); | 3593 __ CallRuntime(Runtime::kToName); |
| 3596 __ bind(&done_convert); | 3594 __ bind(&done_convert); |
| 3597 context()->Plug(r0); | 3595 context()->Plug(r0); |
| 3598 } | 3596 } |
| 3599 | 3597 |
| 3600 | 3598 |
| 3601 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3599 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
| 3602 ZoneList<Expression*>* args = expr->arguments(); | 3600 ZoneList<Expression*>* args = expr->arguments(); |
| 3603 DCHECK(args->length() == 1); | 3601 DCHECK(args->length() == 1); |
| 3604 VisitForAccumulatorValue(args->at(0)); | 3602 VisitForAccumulatorValue(args->at(0)); |
| 3605 | 3603 |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4037 __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); | 4035 __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); |
| 4038 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 4036 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 4039 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | 4037 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); |
| 4040 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); | 4038 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 4041 __ str(r2, FieldMemOperand(r0, JSIteratorResult::kValueOffset)); | 4039 __ str(r2, FieldMemOperand(r0, JSIteratorResult::kValueOffset)); |
| 4042 __ str(r3, FieldMemOperand(r0, JSIteratorResult::kDoneOffset)); | 4040 __ str(r3, FieldMemOperand(r0, JSIteratorResult::kDoneOffset)); |
| 4043 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 4041 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
| 4044 __ b(&done); | 4042 __ b(&done); |
| 4045 | 4043 |
| 4046 __ bind(&runtime); | 4044 __ bind(&runtime); |
| 4047 __ CallRuntime(Runtime::kCreateIterResultObject, 2); | 4045 __ CallRuntime(Runtime::kCreateIterResultObject); |
| 4048 | 4046 |
| 4049 __ bind(&done); | 4047 __ bind(&done); |
| 4050 context()->Plug(r0); | 4048 context()->Plug(r0); |
| 4051 } | 4049 } |
| 4052 | 4050 |
| 4053 | 4051 |
| 4054 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 4052 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
| 4055 // Push undefined as the receiver. | 4053 // Push undefined as the receiver. |
| 4056 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 4054 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 4057 __ push(r0); | 4055 __ push(r0); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4130 case Token::DELETE: { | 4128 case Token::DELETE: { |
| 4131 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4129 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 4132 Property* property = expr->expression()->AsProperty(); | 4130 Property* property = expr->expression()->AsProperty(); |
| 4133 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4131 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 4134 | 4132 |
| 4135 if (property != NULL) { | 4133 if (property != NULL) { |
| 4136 VisitForStackValue(property->obj()); | 4134 VisitForStackValue(property->obj()); |
| 4137 VisitForStackValue(property->key()); | 4135 VisitForStackValue(property->key()); |
| 4138 __ CallRuntime(is_strict(language_mode()) | 4136 __ CallRuntime(is_strict(language_mode()) |
| 4139 ? Runtime::kDeleteProperty_Strict | 4137 ? Runtime::kDeleteProperty_Strict |
| 4140 : Runtime::kDeleteProperty_Sloppy, | 4138 : Runtime::kDeleteProperty_Sloppy); |
| 4141 2); | |
| 4142 context()->Plug(r0); | 4139 context()->Plug(r0); |
| 4143 } else if (proxy != NULL) { | 4140 } else if (proxy != NULL) { |
| 4144 Variable* var = proxy->var(); | 4141 Variable* var = proxy->var(); |
| 4145 // Delete of an unqualified identifier is disallowed in strict mode but | 4142 // Delete of an unqualified identifier is disallowed in strict mode but |
| 4146 // "delete this" is allowed. | 4143 // "delete this" is allowed. |
| 4147 bool is_this = var->HasThisName(isolate()); | 4144 bool is_this = var->HasThisName(isolate()); |
| 4148 DCHECK(is_sloppy(language_mode()) || is_this); | 4145 DCHECK(is_sloppy(language_mode()) || is_this); |
| 4149 if (var->IsUnallocatedOrGlobalSlot()) { | 4146 if (var->IsUnallocatedOrGlobalSlot()) { |
| 4150 __ LoadGlobalObject(r2); | 4147 __ LoadGlobalObject(r2); |
| 4151 __ mov(r1, Operand(var->name())); | 4148 __ mov(r1, Operand(var->name())); |
| 4152 __ Push(r2, r1); | 4149 __ Push(r2, r1); |
| 4153 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); | 4150 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
| 4154 context()->Plug(r0); | 4151 context()->Plug(r0); |
| 4155 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4152 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4156 // Result of deleting non-global, non-dynamic variables is false. | 4153 // Result of deleting non-global, non-dynamic variables is false. |
| 4157 // The subexpression does not have side effects. | 4154 // The subexpression does not have side effects. |
| 4158 context()->Plug(is_this); | 4155 context()->Plug(is_this); |
| 4159 } else { | 4156 } else { |
| 4160 // Non-global variable. Call the runtime to try to delete from the | 4157 // Non-global variable. Call the runtime to try to delete from the |
| 4161 // context where the variable was introduced. | 4158 // context where the variable was introduced. |
| 4162 DCHECK(!context_register().is(r2)); | 4159 DCHECK(!context_register().is(r2)); |
| 4163 __ mov(r2, Operand(var->name())); | 4160 __ mov(r2, Operand(var->name())); |
| 4164 __ Push(context_register(), r2); | 4161 __ Push(context_register(), r2); |
| 4165 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); | 4162 __ CallRuntime(Runtime::kDeleteLookupSlot); |
| 4166 context()->Plug(r0); | 4163 context()->Plug(r0); |
| 4167 } | 4164 } |
| 4168 } else { | 4165 } else { |
| 4169 // Result of deleting non-property, non-variable reference is true. | 4166 // Result of deleting non-property, non-variable reference is true. |
| 4170 // The subexpression may have side effects. | 4167 // The subexpression may have side effects. |
| 4171 VisitForEffect(expr->expression()); | 4168 VisitForEffect(expr->expression()); |
| 4172 context()->Plug(true); | 4169 context()->Plug(true); |
| 4173 } | 4170 } |
| 4174 break; | 4171 break; |
| 4175 } | 4172 } |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4586 Label* if_false = NULL; | 4583 Label* if_false = NULL; |
| 4587 Label* fall_through = NULL; | 4584 Label* fall_through = NULL; |
| 4588 context()->PrepareTest(&materialize_true, &materialize_false, | 4585 context()->PrepareTest(&materialize_true, &materialize_false, |
| 4589 &if_true, &if_false, &fall_through); | 4586 &if_true, &if_false, &fall_through); |
| 4590 | 4587 |
| 4591 Token::Value op = expr->op(); | 4588 Token::Value op = expr->op(); |
| 4592 VisitForStackValue(expr->left()); | 4589 VisitForStackValue(expr->left()); |
| 4593 switch (op) { | 4590 switch (op) { |
| 4594 case Token::IN: | 4591 case Token::IN: |
| 4595 VisitForStackValue(expr->right()); | 4592 VisitForStackValue(expr->right()); |
| 4596 __ CallRuntime(Runtime::kHasProperty, 2); | 4593 __ CallRuntime(Runtime::kHasProperty); |
| 4597 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 4594 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
| 4598 __ CompareRoot(r0, Heap::kTrueValueRootIndex); | 4595 __ CompareRoot(r0, Heap::kTrueValueRootIndex); |
| 4599 Split(eq, if_true, if_false, fall_through); | 4596 Split(eq, if_true, if_false, fall_through); |
| 4600 break; | 4597 break; |
| 4601 | 4598 |
| 4602 case Token::INSTANCEOF: { | 4599 case Token::INSTANCEOF: { |
| 4603 VisitForAccumulatorValue(expr->right()); | 4600 VisitForAccumulatorValue(expr->right()); |
| 4604 __ pop(r1); | 4601 __ pop(r1); |
| 4605 InstanceOfStub stub(isolate()); | 4602 InstanceOfStub stub(isolate()); |
| 4606 __ CallStub(&stub); | 4603 __ CallStub(&stub); |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4920 DCHECK(interrupt_address == | 4917 DCHECK(interrupt_address == |
| 4921 isolate->builtins()->OsrAfterStackCheck()->entry()); | 4918 isolate->builtins()->OsrAfterStackCheck()->entry()); |
| 4922 return OSR_AFTER_STACK_CHECK; | 4919 return OSR_AFTER_STACK_CHECK; |
| 4923 } | 4920 } |
| 4924 | 4921 |
| 4925 | 4922 |
| 4926 } // namespace internal | 4923 } // namespace internal |
| 4927 } // namespace v8 | 4924 } // namespace v8 |
| 4928 | 4925 |
| 4929 #endif // V8_TARGET_ARCH_ARM | 4926 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |