OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 // Generators allocate locals, if any, in context slots. | 142 // Generators allocate locals, if any, in context slots. |
143 DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); | 143 DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); |
144 | 144 |
145 if (locals_count > 0) { | 145 if (locals_count > 0) { |
146 if (locals_count >= 128) { | 146 if (locals_count >= 128) { |
147 Label ok; | 147 Label ok; |
148 DCHECK(jssp.Is(__ StackPointer())); | 148 DCHECK(jssp.Is(__ StackPointer())); |
149 __ Sub(x10, jssp, locals_count * kPointerSize); | 149 __ Sub(x10, jssp, locals_count * kPointerSize); |
150 __ CompareRoot(x10, Heap::kRealStackLimitRootIndex); | 150 __ CompareRoot(x10, Heap::kRealStackLimitRootIndex); |
151 __ B(hs, &ok); | 151 __ B(hs, &ok); |
152 __ CallRuntime(Runtime::kThrowStackOverflow, 0); | 152 __ CallRuntime(Runtime::kThrowStackOverflow); |
153 __ Bind(&ok); | 153 __ Bind(&ok); |
154 } | 154 } |
155 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); | 155 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); |
156 if (FLAG_optimize_for_size) { | 156 if (FLAG_optimize_for_size) { |
157 __ PushMultipleTimes(x10 , locals_count); | 157 __ PushMultipleTimes(x10 , locals_count); |
158 } else { | 158 } else { |
159 const int kMaxPushes = 32; | 159 const int kMaxPushes = 32; |
160 if (locals_count >= kMaxPushes) { | 160 if (locals_count >= kMaxPushes) { |
161 int loop_iterations = locals_count / kMaxPushes; | 161 int loop_iterations = locals_count / kMaxPushes; |
162 __ Mov(x2, loop_iterations); | 162 __ Mov(x2, loop_iterations); |
(...skipping 14 matching lines...) Expand all Loading... |
177 bool function_in_register_x1 = true; | 177 bool function_in_register_x1 = true; |
178 | 178 |
179 if (info->scope()->num_heap_slots() > 0) { | 179 if (info->scope()->num_heap_slots() > 0) { |
180 // Argument to NewContext is the function, which is still in x1. | 180 // Argument to NewContext is the function, which is still in x1. |
181 Comment cmnt(masm_, "[ Allocate context"); | 181 Comment cmnt(masm_, "[ Allocate context"); |
182 bool need_write_barrier = true; | 182 bool need_write_barrier = true; |
183 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 183 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
184 if (info->scope()->is_script_scope()) { | 184 if (info->scope()->is_script_scope()) { |
185 __ Mov(x10, Operand(info->scope()->GetScopeInfo(info->isolate()))); | 185 __ Mov(x10, Operand(info->scope()->GetScopeInfo(info->isolate()))); |
186 __ Push(x1, x10); | 186 __ Push(x1, x10); |
187 __ CallRuntime(Runtime::kNewScriptContext, 2); | 187 __ CallRuntime(Runtime::kNewScriptContext); |
188 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); | 188 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); |
189 // The new target value is not used, clobbering is safe. | 189 // The new target value is not used, clobbering is safe. |
190 DCHECK_NULL(info->scope()->new_target_var()); | 190 DCHECK_NULL(info->scope()->new_target_var()); |
191 } else { | 191 } else { |
192 if (info->scope()->new_target_var() != nullptr) { | 192 if (info->scope()->new_target_var() != nullptr) { |
193 __ Push(x3); // Preserve new target. | 193 __ Push(x3); // Preserve new target. |
194 } | 194 } |
195 if (slots <= FastNewContextStub::kMaximumSlots) { | 195 if (slots <= FastNewContextStub::kMaximumSlots) { |
196 FastNewContextStub stub(isolate(), slots); | 196 FastNewContextStub stub(isolate(), slots); |
197 __ CallStub(&stub); | 197 __ CallStub(&stub); |
198 // Result of FastNewContextStub is always in new space. | 198 // Result of FastNewContextStub is always in new space. |
199 need_write_barrier = false; | 199 need_write_barrier = false; |
200 } else { | 200 } else { |
201 __ Push(x1); | 201 __ Push(x1); |
202 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 202 __ CallRuntime(Runtime::kNewFunctionContext); |
203 } | 203 } |
204 if (info->scope()->new_target_var() != nullptr) { | 204 if (info->scope()->new_target_var() != nullptr) { |
205 __ Pop(x3); // Restore new target. | 205 __ Pop(x3); // Restore new target. |
206 } | 206 } |
207 } | 207 } |
208 function_in_register_x1 = false; | 208 function_in_register_x1 = false; |
209 // Context is returned in x0. It replaces the context passed to us. | 209 // Context is returned in x0. It replaces the context passed to us. |
210 // It's saved in the stack and kept live in cp. | 210 // It's saved in the stack and kept live in cp. |
211 __ Mov(cp, x0); | 211 __ Mov(cp, x0); |
212 __ Str(x0, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 212 __ Str(x0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); | 308 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); |
309 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( | 309 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( |
310 is_unmapped, literal()->has_duplicate_parameters()); | 310 is_unmapped, literal()->has_duplicate_parameters()); |
311 ArgumentsAccessStub stub(isolate(), type); | 311 ArgumentsAccessStub stub(isolate(), type); |
312 __ CallStub(&stub); | 312 __ CallStub(&stub); |
313 | 313 |
314 SetVar(arguments, x0, x1, x2); | 314 SetVar(arguments, x0, x1, x2); |
315 } | 315 } |
316 | 316 |
317 if (FLAG_trace) { | 317 if (FLAG_trace) { |
318 __ CallRuntime(Runtime::kTraceEnter, 0); | 318 __ CallRuntime(Runtime::kTraceEnter); |
319 } | 319 } |
320 | 320 |
321 // Visit the declarations and body unless there is an illegal | 321 // Visit the declarations and body unless there is an illegal |
322 // redeclaration. | 322 // redeclaration. |
323 if (scope()->HasIllegalRedeclaration()) { | 323 if (scope()->HasIllegalRedeclaration()) { |
324 Comment cmnt(masm_, "[ Declarations"); | 324 Comment cmnt(masm_, "[ Declarations"); |
325 VisitForEffect(scope()->GetIllegalRedeclaration()); | 325 VisitForEffect(scope()->GetIllegalRedeclaration()); |
326 | 326 |
327 } else { | 327 } else { |
328 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 328 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 | 434 |
435 if (return_label_.is_bound()) { | 435 if (return_label_.is_bound()) { |
436 __ B(&return_label_); | 436 __ B(&return_label_); |
437 | 437 |
438 } else { | 438 } else { |
439 __ Bind(&return_label_); | 439 __ Bind(&return_label_); |
440 if (FLAG_trace) { | 440 if (FLAG_trace) { |
441 // Push the return value on the stack as the parameter. | 441 // Push the return value on the stack as the parameter. |
442 // Runtime::TraceExit returns its parameter in x0. | 442 // Runtime::TraceExit returns its parameter in x0. |
443 __ Push(result_register()); | 443 __ Push(result_register()); |
444 __ CallRuntime(Runtime::kTraceExit, 1); | 444 __ CallRuntime(Runtime::kTraceExit); |
445 DCHECK(x0.Is(result_register())); | 445 DCHECK(x0.Is(result_register())); |
446 } | 446 } |
447 // Pretend that the exit is a backwards jump to the entry. | 447 // Pretend that the exit is a backwards jump to the entry. |
448 int weight = 1; | 448 int weight = 1; |
449 if (info_->ShouldSelfOptimize()) { | 449 if (info_->ShouldSelfOptimize()) { |
450 weight = FLAG_interrupt_budget / FLAG_self_opt_count; | 450 weight = FLAG_interrupt_budget / FLAG_self_opt_count; |
451 } else { | 451 } else { |
452 int distance = masm_->pc_offset() + kCodeSizeMultiplier / 2; | 452 int distance = masm_->pc_offset() + kCodeSizeMultiplier / 2; |
453 weight = Min(kMaxBackEdgeWeight, | 453 weight = Min(kMaxBackEdgeWeight, |
454 Max(1, distance / kCodeSizeMultiplier)); | 454 Max(1, distance / kCodeSizeMultiplier)); |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 // 'undefined') because we may have a (legal) redeclaration and we | 847 // 'undefined') because we may have a (legal) redeclaration and we |
848 // must not destroy the current value. | 848 // must not destroy the current value. |
849 if (hole_init) { | 849 if (hole_init) { |
850 __ LoadRoot(x0, Heap::kTheHoleValueRootIndex); | 850 __ LoadRoot(x0, Heap::kTheHoleValueRootIndex); |
851 __ Push(x2, x0); | 851 __ Push(x2, x0); |
852 } else { | 852 } else { |
853 // Pushing 0 (xzr) indicates no initial value. | 853 // Pushing 0 (xzr) indicates no initial value. |
854 __ Push(x2, xzr); | 854 __ Push(x2, xzr); |
855 } | 855 } |
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_, "[ Function Declaration"); | 908 Comment cmnt(masm_, "[ Function Declaration"); |
909 __ Mov(x2, Operand(variable->name())); | 909 __ Mov(x2, Operand(variable->name())); |
910 __ Push(x2); | 910 __ Push(x2); |
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(x11, Operand(pairs)); | 923 __ Mov(x11, Operand(pairs)); |
924 Register flags = xzr; | 924 Register flags = xzr; |
925 if (Smi::FromInt(DeclareGlobalsFlags())) { | 925 if (Smi::FromInt(DeclareGlobalsFlags())) { |
926 flags = x10; | 926 flags = x10; |
927 __ Mov(flags, Smi::FromInt(DeclareGlobalsFlags())); | 927 __ Mov(flags, Smi::FromInt(DeclareGlobalsFlags())); |
928 } | 928 } |
929 __ Push(x11, flags); | 929 __ Push(x11, flags); |
930 __ CallRuntime(Runtime::kDeclareGlobals, 2); | 930 __ CallRuntime(Runtime::kDeclareGlobals); |
931 // Return value is ignored. | 931 // Return value is ignored. |
932 } | 932 } |
933 | 933 |
934 | 934 |
935 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 935 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
936 // Call the runtime to declare the modules. | 936 // Call the runtime to declare the modules. |
937 __ Push(descriptions); | 937 __ Push(descriptions); |
938 __ CallRuntime(Runtime::kDeclareModules, 1); | 938 __ CallRuntime(Runtime::kDeclareModules); |
939 // Return value is ignored. | 939 // Return value is ignored. |
940 } | 940 } |
941 | 941 |
942 | 942 |
943 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 943 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
944 ASM_LOCATION("FullCodeGenerator::VisitSwitchStatement"); | 944 ASM_LOCATION("FullCodeGenerator::VisitSwitchStatement"); |
945 Comment cmnt(masm_, "[ SwitchStatement"); | 945 Comment cmnt(masm_, "[ SwitchStatement"); |
946 Breakable nested_statement(this, stmt); | 946 Breakable nested_statement(this, stmt); |
947 SetStatementPosition(stmt); | 947 SetStatementPosition(stmt); |
948 | 948 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 | 1078 |
1079 // The enum cache is valid. Load the map of the object being | 1079 // The enum cache is valid. Load the map of the object being |
1080 // iterated over and use the cache for the iteration. | 1080 // iterated over and use the cache for the iteration. |
1081 Label use_cache; | 1081 Label use_cache; |
1082 __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); | 1082 __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); |
1083 __ B(&use_cache); | 1083 __ B(&use_cache); |
1084 | 1084 |
1085 // Get the set of properties to enumerate. | 1085 // Get the set of properties to enumerate. |
1086 __ Bind(&call_runtime); | 1086 __ Bind(&call_runtime); |
1087 __ Push(x0); // Duplicate the enumerable object on the stack. | 1087 __ Push(x0); // Duplicate the enumerable object on the stack. |
1088 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 1088 __ CallRuntime(Runtime::kGetPropertyNamesFast); |
1089 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); | 1089 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); |
1090 | 1090 |
1091 // If we got a map from the runtime call, we can do a fast | 1091 // If we got a map from the runtime call, we can do a fast |
1092 // modification check. Otherwise, we got a fixed array, and we have | 1092 // modification check. Otherwise, we got a fixed array, and we have |
1093 // to do a slow check. | 1093 // to do a slow check. |
1094 Label fixed_array, no_descriptors; | 1094 Label fixed_array, no_descriptors; |
1095 __ Ldr(x2, FieldMemOperand(x0, HeapObject::kMapOffset)); | 1095 __ Ldr(x2, FieldMemOperand(x0, HeapObject::kMapOffset)); |
1096 __ JumpIfNotRoot(x2, Heap::kMetaMapRootIndex, &fixed_array); | 1096 __ JumpIfNotRoot(x2, Heap::kMetaMapRootIndex, &fixed_array); |
1097 | 1097 |
1098 // We got a map in register x0. Get the enumeration cache from it. | 1098 // We got a map in register x0. Get the enumeration cache from it. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1151 Label update_each; | 1151 Label update_each; |
1152 __ Peek(x1, 4 * kXRegSize); | 1152 __ Peek(x1, 4 * kXRegSize); |
1153 __ Ldr(x11, FieldMemOperand(x1, HeapObject::kMapOffset)); | 1153 __ Ldr(x11, FieldMemOperand(x1, HeapObject::kMapOffset)); |
1154 __ Cmp(x11, x2); | 1154 __ Cmp(x11, x2); |
1155 __ B(eq, &update_each); | 1155 __ B(eq, &update_each); |
1156 | 1156 |
1157 // Convert the entry to a string or (smi) 0 if it isn't a property | 1157 // Convert the entry to a string or (smi) 0 if it isn't a property |
1158 // any more. If the property has been removed while iterating, we | 1158 // any more. If the property has been removed while iterating, we |
1159 // just skip it. | 1159 // just skip it. |
1160 __ Push(x1, x3); | 1160 __ Push(x1, x3); |
1161 __ CallRuntime(Runtime::kForInFilter, 2); | 1161 __ CallRuntime(Runtime::kForInFilter); |
1162 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); | 1162 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); |
1163 __ Mov(x3, x0); | 1163 __ Mov(x3, x0); |
1164 __ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, | 1164 __ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, |
1165 loop_statement.continue_label()); | 1165 loop_statement.continue_label()); |
1166 | 1166 |
1167 // Update the 'each' property or variable from the possibly filtered | 1167 // Update the 'each' property or variable from the possibly filtered |
1168 // entry in register x3. | 1168 // entry in register x3. |
1169 __ Bind(&update_each); | 1169 __ Bind(&update_each); |
1170 __ Mov(result_register(), x3); | 1170 __ Mov(result_register(), x3); |
1171 // Perform the assignment as if via '='. | 1171 // Perform the assignment as if via '='. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 if (!FLAG_always_opt && | 1212 if (!FLAG_always_opt && |
1213 !FLAG_prepare_always_opt && | 1213 !FLAG_prepare_always_opt && |
1214 !pretenure && | 1214 !pretenure && |
1215 scope()->is_function_scope() && | 1215 scope()->is_function_scope() && |
1216 info->num_literals() == 0) { | 1216 info->num_literals() == 0) { |
1217 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); | 1217 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); |
1218 __ Mov(x2, Operand(info)); | 1218 __ Mov(x2, Operand(info)); |
1219 __ CallStub(&stub); | 1219 __ CallStub(&stub); |
1220 } else { | 1220 } else { |
1221 __ Push(info); | 1221 __ Push(info); |
1222 __ CallRuntime( | 1222 __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured |
1223 pretenure ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure, 1); | 1223 : Runtime::kNewClosure); |
1224 } | 1224 } |
1225 context()->Plug(x0); | 1225 context()->Plug(x0); |
1226 } | 1226 } |
1227 | 1227 |
1228 | 1228 |
1229 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, | 1229 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, |
1230 FeedbackVectorSlot slot) { | 1230 FeedbackVectorSlot slot) { |
1231 DCHECK(NeedsHomeObject(initializer)); | 1231 DCHECK(NeedsHomeObject(initializer)); |
1232 __ Peek(StoreDescriptor::ReceiverRegister(), 0); | 1232 __ Peek(StoreDescriptor::ReceiverRegister(), 0); |
1233 __ Mov(StoreDescriptor::NameRegister(), | 1233 __ Mov(StoreDescriptor::NameRegister(), |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1346 Variable* local = var->local_if_not_shadowed(); | 1346 Variable* local = var->local_if_not_shadowed(); |
1347 __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); | 1347 __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); |
1348 if (local->mode() == LET || local->mode() == CONST || | 1348 if (local->mode() == LET || local->mode() == CONST || |
1349 local->mode() == CONST_LEGACY) { | 1349 local->mode() == CONST_LEGACY) { |
1350 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); | 1350 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); |
1351 if (local->mode() == CONST_LEGACY) { | 1351 if (local->mode() == CONST_LEGACY) { |
1352 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1352 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
1353 } else { // LET || CONST | 1353 } else { // LET || CONST |
1354 __ Mov(x0, Operand(var->name())); | 1354 __ Mov(x0, Operand(var->name())); |
1355 __ Push(x0); | 1355 __ Push(x0); |
1356 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1356 __ CallRuntime(Runtime::kThrowReferenceError); |
1357 } | 1357 } |
1358 } | 1358 } |
1359 __ B(done); | 1359 __ B(done); |
1360 } | 1360 } |
1361 } | 1361 } |
1362 | 1362 |
1363 | 1363 |
1364 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1364 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
1365 TypeofMode typeof_mode) { | 1365 TypeofMode typeof_mode) { |
1366 Variable* var = proxy->var(); | 1366 Variable* var = proxy->var(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1402 if (NeedsHoleCheckForLoad(proxy)) { | 1402 if (NeedsHoleCheckForLoad(proxy)) { |
1403 // Let and const need a read barrier. | 1403 // Let and const need a read barrier. |
1404 GetVar(x0, var); | 1404 GetVar(x0, var); |
1405 Label done; | 1405 Label done; |
1406 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); | 1406 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); |
1407 if (var->mode() == LET || var->mode() == CONST) { | 1407 if (var->mode() == LET || var->mode() == CONST) { |
1408 // Throw a reference error when using an uninitialized let/const | 1408 // Throw a reference error when using an uninitialized let/const |
1409 // binding in harmony mode. | 1409 // binding in harmony mode. |
1410 __ Mov(x0, Operand(var->name())); | 1410 __ Mov(x0, Operand(var->name())); |
1411 __ Push(x0); | 1411 __ Push(x0); |
1412 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1412 __ CallRuntime(Runtime::kThrowReferenceError); |
1413 __ Bind(&done); | 1413 __ Bind(&done); |
1414 } else { | 1414 } else { |
1415 // Uninitialized legacy const bindings are unholed. | 1415 // Uninitialized legacy const bindings are unholed. |
1416 DCHECK(var->mode() == CONST_LEGACY); | 1416 DCHECK(var->mode() == CONST_LEGACY); |
1417 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1417 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
1418 __ Bind(&done); | 1418 __ Bind(&done); |
1419 } | 1419 } |
1420 context()->Plug(x0); | 1420 context()->Plug(x0); |
1421 break; | 1421 break; |
1422 } | 1422 } |
1423 context()->Plug(var); | 1423 context()->Plug(var); |
1424 break; | 1424 break; |
1425 } | 1425 } |
1426 | 1426 |
1427 case VariableLocation::LOOKUP: { | 1427 case VariableLocation::LOOKUP: { |
1428 Label done, slow; | 1428 Label done, slow; |
1429 // Generate code for loading from variables potentially shadowed by | 1429 // Generate code for loading from variables potentially shadowed by |
1430 // eval-introduced variables. | 1430 // eval-introduced variables. |
1431 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | 1431 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); |
1432 __ Bind(&slow); | 1432 __ Bind(&slow); |
1433 Comment cmnt(masm_, "Lookup variable"); | 1433 Comment cmnt(masm_, "Lookup variable"); |
1434 __ Mov(x1, Operand(var->name())); | 1434 __ Mov(x1, Operand(var->name())); |
1435 __ Push(cp, x1); // Context and name. | 1435 __ Push(cp, x1); // Context and name. |
1436 Runtime::FunctionId function_id = | 1436 Runtime::FunctionId function_id = |
1437 typeof_mode == NOT_INSIDE_TYPEOF | 1437 typeof_mode == NOT_INSIDE_TYPEOF |
1438 ? Runtime::kLoadLookupSlot | 1438 ? Runtime::kLoadLookupSlot |
1439 : Runtime::kLoadLookupSlotNoReferenceError; | 1439 : Runtime::kLoadLookupSlotNoReferenceError; |
1440 __ CallRuntime(function_id, 2); | 1440 __ CallRuntime(function_id); |
1441 __ Bind(&done); | 1441 __ Bind(&done); |
1442 context()->Plug(x0); | 1442 context()->Plug(x0); |
1443 break; | 1443 break; |
1444 } | 1444 } |
1445 } | 1445 } |
1446 } | 1446 } |
1447 | 1447 |
1448 | 1448 |
1449 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1449 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1450 Comment cmnt(masm_, "[ RegExpLiteral"); | 1450 Comment cmnt(masm_, "[ RegExpLiteral"); |
(...skipping 28 matching lines...) Expand all Loading... |
1479 Comment cmnt(masm_, "[ ObjectLiteral"); | 1479 Comment cmnt(masm_, "[ ObjectLiteral"); |
1480 | 1480 |
1481 Handle<FixedArray> constant_properties = expr->constant_properties(); | 1481 Handle<FixedArray> constant_properties = expr->constant_properties(); |
1482 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1482 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
1483 __ Mov(x2, Smi::FromInt(expr->literal_index())); | 1483 __ Mov(x2, Smi::FromInt(expr->literal_index())); |
1484 __ Mov(x1, Operand(constant_properties)); | 1484 __ Mov(x1, Operand(constant_properties)); |
1485 int flags = expr->ComputeFlags(); | 1485 int flags = expr->ComputeFlags(); |
1486 __ Mov(x0, Smi::FromInt(flags)); | 1486 __ Mov(x0, Smi::FromInt(flags)); |
1487 if (MustCreateObjectLiteralWithRuntime(expr)) { | 1487 if (MustCreateObjectLiteralWithRuntime(expr)) { |
1488 __ Push(x3, x2, x1, x0); | 1488 __ Push(x3, x2, x1, x0); |
1489 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1489 __ CallRuntime(Runtime::kCreateObjectLiteral); |
1490 } else { | 1490 } else { |
1491 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1491 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
1492 __ CallStub(&stub); | 1492 __ CallStub(&stub); |
1493 } | 1493 } |
1494 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1494 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
1495 | 1495 |
1496 // If result_saved is true the result is on top of the stack. If | 1496 // If result_saved is true the result is on top of the stack. If |
1497 // result_saved is false the result is in x0. | 1497 // result_saved is false the result is in x0. |
1498 bool result_saved = false; | 1498 bool result_saved = false; |
1499 | 1499 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1540 __ Peek(x0, 0); | 1540 __ Peek(x0, 0); |
1541 __ Push(x0); | 1541 __ Push(x0); |
1542 VisitForStackValue(key); | 1542 VisitForStackValue(key); |
1543 VisitForStackValue(value); | 1543 VisitForStackValue(value); |
1544 if (property->emit_store()) { | 1544 if (property->emit_store()) { |
1545 if (NeedsHomeObject(value)) { | 1545 if (NeedsHomeObject(value)) { |
1546 EmitSetHomeObject(value, 2, property->GetSlot()); | 1546 EmitSetHomeObject(value, 2, property->GetSlot()); |
1547 } | 1547 } |
1548 __ Mov(x0, Smi::FromInt(SLOPPY)); // Language mode | 1548 __ Mov(x0, Smi::FromInt(SLOPPY)); // Language mode |
1549 __ Push(x0); | 1549 __ Push(x0); |
1550 __ CallRuntime(Runtime::kSetProperty, 4); | 1550 __ CallRuntime(Runtime::kSetProperty); |
1551 } else { | 1551 } else { |
1552 __ Drop(3); | 1552 __ Drop(3); |
1553 } | 1553 } |
1554 break; | 1554 break; |
1555 case ObjectLiteral::Property::PROTOTYPE: | 1555 case ObjectLiteral::Property::PROTOTYPE: |
1556 DCHECK(property->emit_store()); | 1556 DCHECK(property->emit_store()); |
1557 // Duplicate receiver on stack. | 1557 // Duplicate receiver on stack. |
1558 __ Peek(x0, 0); | 1558 __ Peek(x0, 0); |
1559 __ Push(x0); | 1559 __ Push(x0); |
1560 VisitForStackValue(value); | 1560 VisitForStackValue(value); |
1561 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1561 __ CallRuntime(Runtime::kInternalSetPrototype); |
1562 break; | 1562 break; |
1563 case ObjectLiteral::Property::GETTER: | 1563 case ObjectLiteral::Property::GETTER: |
1564 if (property->emit_store()) { | 1564 if (property->emit_store()) { |
1565 accessor_table.lookup(key)->second->getter = property; | 1565 accessor_table.lookup(key)->second->getter = property; |
1566 } | 1566 } |
1567 break; | 1567 break; |
1568 case ObjectLiteral::Property::SETTER: | 1568 case ObjectLiteral::Property::SETTER: |
1569 if (property->emit_store()) { | 1569 if (property->emit_store()) { |
1570 accessor_table.lookup(key)->second->setter = property; | 1570 accessor_table.lookup(key)->second->setter = property; |
1571 } | 1571 } |
1572 break; | 1572 break; |
1573 } | 1573 } |
1574 } | 1574 } |
1575 | 1575 |
1576 // Emit code to define accessors, using only a single call to the runtime for | 1576 // Emit code to define accessors, using only a single call to the runtime for |
1577 // each pair of corresponding getters and setters. | 1577 // each pair of corresponding getters and setters. |
1578 for (AccessorTable::Iterator it = accessor_table.begin(); | 1578 for (AccessorTable::Iterator it = accessor_table.begin(); |
1579 it != accessor_table.end(); | 1579 it != accessor_table.end(); |
1580 ++it) { | 1580 ++it) { |
1581 __ Peek(x10, 0); // Duplicate receiver. | 1581 __ Peek(x10, 0); // Duplicate receiver. |
1582 __ Push(x10); | 1582 __ Push(x10); |
1583 VisitForStackValue(it->first); | 1583 VisitForStackValue(it->first); |
1584 EmitAccessor(it->second->getter); | 1584 EmitAccessor(it->second->getter); |
1585 EmitAccessor(it->second->setter); | 1585 EmitAccessor(it->second->setter); |
1586 __ Mov(x10, Smi::FromInt(NONE)); | 1586 __ Mov(x10, Smi::FromInt(NONE)); |
1587 __ Push(x10); | 1587 __ Push(x10); |
1588 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1588 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); |
1589 } | 1589 } |
1590 | 1590 |
1591 // Object literals have two parts. The "static" part on the left contains no | 1591 // Object literals have two parts. The "static" part on the left contains no |
1592 // computed property names, and so we can compute its map ahead of time; see | 1592 // computed property names, and so we can compute its map ahead of time; see |
1593 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part | 1593 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
1594 // starts with the first computed property name, and continues with all | 1594 // starts with the first computed property name, and continues with all |
1595 // properties to its right. All the code from above initializes the static | 1595 // properties to its right. All the code from above initializes the static |
1596 // component of the object literal, and arranges for the map of the result to | 1596 // component of the object literal, and arranges for the map of the result to |
1597 // reflect the static order in which the keys appear. For the dynamic | 1597 // reflect the static order in which the keys appear. For the dynamic |
1598 // properties, we compile them into a series of "SetOwnProperty" runtime | 1598 // properties, we compile them into a series of "SetOwnProperty" runtime |
1599 // calls. This will preserve insertion order. | 1599 // calls. This will preserve insertion order. |
1600 for (; property_index < expr->properties()->length(); property_index++) { | 1600 for (; property_index < expr->properties()->length(); property_index++) { |
1601 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1601 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
1602 | 1602 |
1603 Expression* value = property->value(); | 1603 Expression* value = property->value(); |
1604 if (!result_saved) { | 1604 if (!result_saved) { |
1605 __ Push(x0); // Save result on stack | 1605 __ Push(x0); // Save result on stack |
1606 result_saved = true; | 1606 result_saved = true; |
1607 } | 1607 } |
1608 | 1608 |
1609 __ Peek(x10, 0); // Duplicate receiver. | 1609 __ Peek(x10, 0); // Duplicate receiver. |
1610 __ Push(x10); | 1610 __ Push(x10); |
1611 | 1611 |
1612 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1612 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
1613 DCHECK(!property->is_computed_name()); | 1613 DCHECK(!property->is_computed_name()); |
1614 VisitForStackValue(value); | 1614 VisitForStackValue(value); |
1615 DCHECK(property->emit_store()); | 1615 DCHECK(property->emit_store()); |
1616 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1616 __ CallRuntime(Runtime::kInternalSetPrototype); |
1617 } else { | 1617 } else { |
1618 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); | 1618 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); |
1619 VisitForStackValue(value); | 1619 VisitForStackValue(value); |
1620 if (NeedsHomeObject(value)) { | 1620 if (NeedsHomeObject(value)) { |
1621 EmitSetHomeObject(value, 2, property->GetSlot()); | 1621 EmitSetHomeObject(value, 2, property->GetSlot()); |
1622 } | 1622 } |
1623 | 1623 |
1624 switch (property->kind()) { | 1624 switch (property->kind()) { |
1625 case ObjectLiteral::Property::CONSTANT: | 1625 case ObjectLiteral::Property::CONSTANT: |
1626 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1626 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1627 case ObjectLiteral::Property::COMPUTED: | 1627 case ObjectLiteral::Property::COMPUTED: |
1628 if (property->emit_store()) { | 1628 if (property->emit_store()) { |
1629 __ Mov(x0, Smi::FromInt(NONE)); | 1629 __ Mov(x0, Smi::FromInt(NONE)); |
1630 __ Push(x0); | 1630 __ Push(x0); |
1631 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); | 1631 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked); |
1632 } else { | 1632 } else { |
1633 __ Drop(3); | 1633 __ Drop(3); |
1634 } | 1634 } |
1635 break; | 1635 break; |
1636 | 1636 |
1637 case ObjectLiteral::Property::PROTOTYPE: | 1637 case ObjectLiteral::Property::PROTOTYPE: |
1638 UNREACHABLE(); | 1638 UNREACHABLE(); |
1639 break; | 1639 break; |
1640 | 1640 |
1641 case ObjectLiteral::Property::GETTER: | 1641 case ObjectLiteral::Property::GETTER: |
1642 __ Mov(x0, Smi::FromInt(NONE)); | 1642 __ Mov(x0, Smi::FromInt(NONE)); |
1643 __ Push(x0); | 1643 __ Push(x0); |
1644 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 1644 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
1645 break; | 1645 break; |
1646 | 1646 |
1647 case ObjectLiteral::Property::SETTER: | 1647 case ObjectLiteral::Property::SETTER: |
1648 __ Mov(x0, Smi::FromInt(NONE)); | 1648 __ Mov(x0, Smi::FromInt(NONE)); |
1649 __ Push(x0); | 1649 __ Push(x0); |
1650 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 1650 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
1651 break; | 1651 break; |
1652 } | 1652 } |
1653 } | 1653 } |
1654 } | 1654 } |
1655 | 1655 |
1656 if (expr->has_function()) { | 1656 if (expr->has_function()) { |
1657 DCHECK(result_saved); | 1657 DCHECK(result_saved); |
1658 __ Peek(x0, 0); | 1658 __ Peek(x0, 0); |
1659 __ Push(x0); | 1659 __ Push(x0); |
1660 __ CallRuntime(Runtime::kToFastProperties, 1); | 1660 __ CallRuntime(Runtime::kToFastProperties); |
1661 } | 1661 } |
1662 | 1662 |
1663 if (result_saved) { | 1663 if (result_saved) { |
1664 context()->PlugTOS(); | 1664 context()->PlugTOS(); |
1665 } else { | 1665 } else { |
1666 context()->Plug(x0); | 1666 context()->Plug(x0); |
1667 } | 1667 } |
1668 } | 1668 } |
1669 | 1669 |
1670 | 1670 |
(...skipping 10 matching lines...) Expand all Loading... |
1681 // we can turn it off if we don't have anywhere else to transition to. | 1681 // we can turn it off if we don't have anywhere else to transition to. |
1682 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1682 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
1683 } | 1683 } |
1684 | 1684 |
1685 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1685 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
1686 __ Mov(x2, Smi::FromInt(expr->literal_index())); | 1686 __ Mov(x2, Smi::FromInt(expr->literal_index())); |
1687 __ Mov(x1, Operand(constant_elements)); | 1687 __ Mov(x1, Operand(constant_elements)); |
1688 if (MustCreateArrayLiteralWithRuntime(expr)) { | 1688 if (MustCreateArrayLiteralWithRuntime(expr)) { |
1689 __ Mov(x0, Smi::FromInt(expr->ComputeFlags())); | 1689 __ Mov(x0, Smi::FromInt(expr->ComputeFlags())); |
1690 __ Push(x3, x2, x1, x0); | 1690 __ Push(x3, x2, x1, x0); |
1691 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); | 1691 __ CallRuntime(Runtime::kCreateArrayLiteral); |
1692 } else { | 1692 } else { |
1693 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1693 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
1694 __ CallStub(&stub); | 1694 __ CallStub(&stub); |
1695 } | 1695 } |
1696 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1696 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
1697 | 1697 |
1698 bool result_saved = false; // Is the result saved to the stack? | 1698 bool result_saved = false; // Is the result saved to the stack? |
1699 ZoneList<Expression*>* subexprs = expr->values(); | 1699 ZoneList<Expression*>* subexprs = expr->values(); |
1700 int length = subexprs->length(); | 1700 int length = subexprs->length(); |
1701 | 1701 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1738 for (; array_index < length; array_index++) { | 1738 for (; array_index < length; array_index++) { |
1739 Expression* subexpr = subexprs->at(array_index); | 1739 Expression* subexpr = subexprs->at(array_index); |
1740 | 1740 |
1741 __ Push(x0); | 1741 __ Push(x0); |
1742 if (subexpr->IsSpread()) { | 1742 if (subexpr->IsSpread()) { |
1743 VisitForStackValue(subexpr->AsSpread()->expression()); | 1743 VisitForStackValue(subexpr->AsSpread()->expression()); |
1744 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, | 1744 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, |
1745 CALL_FUNCTION); | 1745 CALL_FUNCTION); |
1746 } else { | 1746 } else { |
1747 VisitForStackValue(subexpr); | 1747 VisitForStackValue(subexpr); |
1748 __ CallRuntime(Runtime::kAppendElement, 2); | 1748 __ CallRuntime(Runtime::kAppendElement); |
1749 } | 1749 } |
1750 | 1750 |
1751 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); | 1751 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
1752 } | 1752 } |
1753 | 1753 |
1754 if (result_saved) { | 1754 if (result_saved) { |
1755 context()->PlugTOS(); | 1755 context()->PlugTOS(); |
1756 } else { | 1756 } else { |
1757 context()->Plug(x0); | 1757 context()->Plug(x0); |
1758 } | 1758 } |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1912 | 1912 |
1913 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { | 1913 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
1914 // Stack: receiver, home_object. | 1914 // Stack: receiver, home_object. |
1915 SetExpressionPosition(prop); | 1915 SetExpressionPosition(prop); |
1916 Literal* key = prop->key()->AsLiteral(); | 1916 Literal* key = prop->key()->AsLiteral(); |
1917 DCHECK(!key->value()->IsSmi()); | 1917 DCHECK(!key->value()->IsSmi()); |
1918 DCHECK(prop->IsSuperAccess()); | 1918 DCHECK(prop->IsSuperAccess()); |
1919 | 1919 |
1920 __ Push(key->value()); | 1920 __ Push(key->value()); |
1921 __ Push(Smi::FromInt(language_mode())); | 1921 __ Push(Smi::FromInt(language_mode())); |
1922 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 1922 __ CallRuntime(Runtime::kLoadFromSuper); |
1923 } | 1923 } |
1924 | 1924 |
1925 | 1925 |
1926 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1926 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1927 SetExpressionPosition(prop); | 1927 SetExpressionPosition(prop); |
1928 // Call keyed load IC. It has arguments key and receiver in x0 and x1. | 1928 // Call keyed load IC. It has arguments key and receiver in x0 and x1. |
1929 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); | 1929 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); |
1930 __ Mov(LoadDescriptor::SlotRegister(), | 1930 __ Mov(LoadDescriptor::SlotRegister(), |
1931 SmiFromSlot(prop->PropertyFeedbackSlot())); | 1931 SmiFromSlot(prop->PropertyFeedbackSlot())); |
1932 CallIC(ic); | 1932 CallIC(ic); |
1933 } | 1933 } |
1934 | 1934 |
1935 | 1935 |
1936 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { | 1936 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
1937 // Stack: receiver, home_object, key. | 1937 // Stack: receiver, home_object, key. |
1938 SetExpressionPosition(prop); | 1938 SetExpressionPosition(prop); |
1939 __ Push(Smi::FromInt(language_mode())); | 1939 __ Push(Smi::FromInt(language_mode())); |
1940 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 1940 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
1941 } | 1941 } |
1942 | 1942 |
1943 | 1943 |
1944 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1944 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
1945 Token::Value op, | 1945 Token::Value op, |
1946 Expression* left_expr, | 1946 Expression* left_expr, |
1947 Expression* right_expr) { | 1947 Expression* right_expr) { |
1948 Label done, both_smis, stub_call; | 1948 Label done, both_smis, stub_call; |
1949 | 1949 |
1950 // Get the arguments. | 1950 // Get the arguments. |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2077 __ Peek(scratch, 0); // prototype | 2077 __ Peek(scratch, 0); // prototype |
2078 } | 2078 } |
2079 __ Push(scratch); | 2079 __ Push(scratch); |
2080 EmitPropertyKey(property, lit->GetIdForProperty(i)); | 2080 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
2081 | 2081 |
2082 // The static prototype property is read only. We handle the non computed | 2082 // The static prototype property is read only. We handle the non computed |
2083 // property name case in the parser. Since this is the only case where we | 2083 // property name case in the parser. Since this is the only case where we |
2084 // need to check for an own read only property we special case this so we do | 2084 // need to check for an own read only property we special case this so we do |
2085 // not need to do this for every property. | 2085 // not need to do this for every property. |
2086 if (property->is_static() && property->is_computed_name()) { | 2086 if (property->is_static() && property->is_computed_name()) { |
2087 __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1); | 2087 __ CallRuntime(Runtime::kThrowIfStaticPrototype); |
2088 __ Push(x0); | 2088 __ Push(x0); |
2089 } | 2089 } |
2090 | 2090 |
2091 VisitForStackValue(value); | 2091 VisitForStackValue(value); |
2092 if (NeedsHomeObject(value)) { | 2092 if (NeedsHomeObject(value)) { |
2093 EmitSetHomeObject(value, 2, property->GetSlot()); | 2093 EmitSetHomeObject(value, 2, property->GetSlot()); |
2094 } | 2094 } |
2095 | 2095 |
2096 switch (property->kind()) { | 2096 switch (property->kind()) { |
2097 case ObjectLiteral::Property::CONSTANT: | 2097 case ObjectLiteral::Property::CONSTANT: |
2098 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2098 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
2099 case ObjectLiteral::Property::PROTOTYPE: | 2099 case ObjectLiteral::Property::PROTOTYPE: |
2100 UNREACHABLE(); | 2100 UNREACHABLE(); |
2101 case ObjectLiteral::Property::COMPUTED: | 2101 case ObjectLiteral::Property::COMPUTED: |
2102 __ CallRuntime(Runtime::kDefineClassMethod, 3); | 2102 __ CallRuntime(Runtime::kDefineClassMethod); |
2103 break; | 2103 break; |
2104 | 2104 |
2105 case ObjectLiteral::Property::GETTER: | 2105 case ObjectLiteral::Property::GETTER: |
2106 __ Mov(x0, Smi::FromInt(DONT_ENUM)); | 2106 __ Mov(x0, Smi::FromInt(DONT_ENUM)); |
2107 __ Push(x0); | 2107 __ Push(x0); |
2108 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 2108 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
2109 break; | 2109 break; |
2110 | 2110 |
2111 case ObjectLiteral::Property::SETTER: | 2111 case ObjectLiteral::Property::SETTER: |
2112 __ Mov(x0, Smi::FromInt(DONT_ENUM)); | 2112 __ Mov(x0, Smi::FromInt(DONT_ENUM)); |
2113 __ Push(x0); | 2113 __ Push(x0); |
2114 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 2114 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
2115 break; | 2115 break; |
2116 | 2116 |
2117 default: | 2117 default: |
2118 UNREACHABLE(); | 2118 UNREACHABLE(); |
2119 } | 2119 } |
2120 } | 2120 } |
2121 | 2121 |
2122 // Set both the prototype and constructor to have fast properties, and also | 2122 // Set both the prototype and constructor to have fast properties, and also |
2123 // freeze them in strong mode. | 2123 // freeze them in strong mode. |
2124 __ CallRuntime(Runtime::kFinalizeClassDefinition, 2); | 2124 __ CallRuntime(Runtime::kFinalizeClassDefinition); |
2125 } | 2125 } |
2126 | 2126 |
2127 | 2127 |
2128 void FullCodeGenerator::EmitAssignment(Expression* expr, | 2128 void FullCodeGenerator::EmitAssignment(Expression* expr, |
2129 FeedbackVectorSlot slot) { | 2129 FeedbackVectorSlot slot) { |
2130 DCHECK(expr->IsValidReferenceExpressionOrThis()); | 2130 DCHECK(expr->IsValidReferenceExpressionOrThis()); |
2131 | 2131 |
2132 Property* prop = expr->AsProperty(); | 2132 Property* prop = expr->AsProperty(); |
2133 LhsKind assign_type = Property::GetAssignType(prop); | 2133 LhsKind assign_type = Property::GetAssignType(prop); |
2134 | 2134 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2233 } else if (var->mode() == LET && op != Token::INIT) { | 2233 } else if (var->mode() == LET && op != Token::INIT) { |
2234 // Non-initializing assignment to let variable needs a write barrier. | 2234 // Non-initializing assignment to let variable needs a write barrier. |
2235 DCHECK(!var->IsLookupSlot()); | 2235 DCHECK(!var->IsLookupSlot()); |
2236 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2236 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2237 Label assign; | 2237 Label assign; |
2238 MemOperand location = VarOperand(var, x1); | 2238 MemOperand location = VarOperand(var, x1); |
2239 __ Ldr(x10, location); | 2239 __ Ldr(x10, location); |
2240 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign); | 2240 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign); |
2241 __ Mov(x10, Operand(var->name())); | 2241 __ Mov(x10, Operand(var->name())); |
2242 __ Push(x10); | 2242 __ Push(x10); |
2243 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2243 __ CallRuntime(Runtime::kThrowReferenceError); |
2244 // Perform the assignment. | 2244 // Perform the assignment. |
2245 __ Bind(&assign); | 2245 __ Bind(&assign); |
2246 EmitStoreToStackLocalOrContextSlot(var, location); | 2246 EmitStoreToStackLocalOrContextSlot(var, location); |
2247 | 2247 |
2248 } else if (var->mode() == CONST && op != Token::INIT) { | 2248 } else if (var->mode() == CONST && op != Token::INIT) { |
2249 // Assignment to const variable needs a write barrier. | 2249 // Assignment to const variable needs a write barrier. |
2250 DCHECK(!var->IsLookupSlot()); | 2250 DCHECK(!var->IsLookupSlot()); |
2251 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2251 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2252 Label const_error; | 2252 Label const_error; |
2253 MemOperand location = VarOperand(var, x1); | 2253 MemOperand location = VarOperand(var, x1); |
2254 __ Ldr(x10, location); | 2254 __ Ldr(x10, location); |
2255 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &const_error); | 2255 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &const_error); |
2256 __ Mov(x10, Operand(var->name())); | 2256 __ Mov(x10, Operand(var->name())); |
2257 __ Push(x10); | 2257 __ Push(x10); |
2258 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2258 __ CallRuntime(Runtime::kThrowReferenceError); |
2259 __ Bind(&const_error); | 2259 __ Bind(&const_error); |
2260 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2260 __ CallRuntime(Runtime::kThrowConstAssignError); |
2261 | 2261 |
2262 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | 2262 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
2263 // Initializing assignment to const {this} needs a write barrier. | 2263 // Initializing assignment to const {this} needs a write barrier. |
2264 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2264 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2265 Label uninitialized_this; | 2265 Label uninitialized_this; |
2266 MemOperand location = VarOperand(var, x1); | 2266 MemOperand location = VarOperand(var, x1); |
2267 __ Ldr(x10, location); | 2267 __ Ldr(x10, location); |
2268 __ JumpIfRoot(x10, Heap::kTheHoleValueRootIndex, &uninitialized_this); | 2268 __ JumpIfRoot(x10, Heap::kTheHoleValueRootIndex, &uninitialized_this); |
2269 __ Mov(x0, Operand(var->name())); | 2269 __ Mov(x0, Operand(var->name())); |
2270 __ Push(x0); | 2270 __ Push(x0); |
2271 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2271 __ CallRuntime(Runtime::kThrowReferenceError); |
2272 __ bind(&uninitialized_this); | 2272 __ bind(&uninitialized_this); |
2273 EmitStoreToStackLocalOrContextSlot(var, location); | 2273 EmitStoreToStackLocalOrContextSlot(var, location); |
2274 | 2274 |
2275 } else if (!var->is_const_mode() || | 2275 } else if (!var->is_const_mode() || |
2276 (var->mode() == CONST && op == Token::INIT)) { | 2276 (var->mode() == CONST && op == Token::INIT)) { |
2277 if (var->IsLookupSlot()) { | 2277 if (var->IsLookupSlot()) { |
2278 // Assignment to var. | 2278 // Assignment to var. |
2279 __ Mov(x11, Operand(var->name())); | 2279 __ Mov(x11, Operand(var->name())); |
2280 __ Mov(x10, Smi::FromInt(language_mode())); | 2280 __ Mov(x10, Smi::FromInt(language_mode())); |
2281 // jssp[0] : mode. | 2281 // jssp[0] : mode. |
2282 // jssp[8] : name. | 2282 // jssp[8] : name. |
2283 // jssp[16] : context. | 2283 // jssp[16] : context. |
2284 // jssp[24] : value. | 2284 // jssp[24] : value. |
2285 __ Push(x0, cp, x11, x10); | 2285 __ Push(x0, cp, x11, x10); |
2286 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2286 __ CallRuntime(Runtime::kStoreLookupSlot); |
2287 } else { | 2287 } else { |
2288 // Assignment to var or initializing assignment to let/const in harmony | 2288 // Assignment to var or initializing assignment to let/const in harmony |
2289 // mode. | 2289 // mode. |
2290 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2290 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2291 MemOperand location = VarOperand(var, x1); | 2291 MemOperand location = VarOperand(var, x1); |
2292 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | 2292 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
2293 __ Ldr(x10, location); | 2293 __ Ldr(x10, location); |
2294 __ CompareRoot(x10, Heap::kTheHoleValueRootIndex); | 2294 __ CompareRoot(x10, Heap::kTheHoleValueRootIndex); |
2295 __ Check(eq, kLetBindingReInitialization); | 2295 __ Check(eq, kLetBindingReInitialization); |
2296 } | 2296 } |
2297 EmitStoreToStackLocalOrContextSlot(var, location); | 2297 EmitStoreToStackLocalOrContextSlot(var, location); |
2298 } | 2298 } |
2299 | 2299 |
2300 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { | 2300 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { |
2301 // Const initializers need a write barrier. | 2301 // Const initializers need a write barrier. |
2302 DCHECK(!var->IsParameter()); // No const parameters. | 2302 DCHECK(!var->IsParameter()); // No const parameters. |
2303 if (var->IsLookupSlot()) { | 2303 if (var->IsLookupSlot()) { |
2304 __ Mov(x1, Operand(var->name())); | 2304 __ Mov(x1, Operand(var->name())); |
2305 __ Push(x0, cp, x1); | 2305 __ Push(x0, cp, x1); |
2306 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2306 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot); |
2307 } else { | 2307 } else { |
2308 DCHECK(var->IsStackLocal() || var->IsContextSlot()); | 2308 DCHECK(var->IsStackLocal() || var->IsContextSlot()); |
2309 Label skip; | 2309 Label skip; |
2310 MemOperand location = VarOperand(var, x1); | 2310 MemOperand location = VarOperand(var, x1); |
2311 __ Ldr(x10, location); | 2311 __ Ldr(x10, location); |
2312 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &skip); | 2312 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &skip); |
2313 EmitStoreToStackLocalOrContextSlot(var, location); | 2313 EmitStoreToStackLocalOrContextSlot(var, location); |
2314 __ Bind(&skip); | 2314 __ Bind(&skip); |
2315 } | 2315 } |
2316 | 2316 |
2317 } else { | 2317 } else { |
2318 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); | 2318 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); |
2319 if (is_strict(language_mode())) { | 2319 if (is_strict(language_mode())) { |
2320 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2320 __ CallRuntime(Runtime::kThrowConstAssignError); |
2321 } | 2321 } |
2322 // Silently ignore store in sloppy mode. | 2322 // Silently ignore store in sloppy mode. |
2323 } | 2323 } |
2324 } | 2324 } |
2325 | 2325 |
2326 | 2326 |
2327 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2327 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2328 ASM_LOCATION("FullCodeGenerator::EmitNamedPropertyAssignment"); | 2328 ASM_LOCATION("FullCodeGenerator::EmitNamedPropertyAssignment"); |
2329 // Assignment to a property, using a named store IC. | 2329 // Assignment to a property, using a named store IC. |
2330 Property* prop = expr->target()->AsProperty(); | 2330 Property* prop = expr->target()->AsProperty(); |
(...skipping 15 matching lines...) Expand all Loading... |
2346 // Assignment to named property of super. | 2346 // Assignment to named property of super. |
2347 // x0 : value | 2347 // x0 : value |
2348 // stack : receiver ('this'), home_object | 2348 // stack : receiver ('this'), home_object |
2349 DCHECK(prop != NULL); | 2349 DCHECK(prop != NULL); |
2350 Literal* key = prop->key()->AsLiteral(); | 2350 Literal* key = prop->key()->AsLiteral(); |
2351 DCHECK(key != NULL); | 2351 DCHECK(key != NULL); |
2352 | 2352 |
2353 __ Push(key->value()); | 2353 __ Push(key->value()); |
2354 __ Push(x0); | 2354 __ Push(x0); |
2355 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict | 2355 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
2356 : Runtime::kStoreToSuper_Sloppy), | 2356 : Runtime::kStoreToSuper_Sloppy)); |
2357 4); | |
2358 } | 2357 } |
2359 | 2358 |
2360 | 2359 |
2361 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { | 2360 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
2362 // Assignment to named property of super. | 2361 // Assignment to named property of super. |
2363 // x0 : value | 2362 // x0 : value |
2364 // stack : receiver ('this'), home_object, key | 2363 // stack : receiver ('this'), home_object, key |
2365 DCHECK(prop != NULL); | 2364 DCHECK(prop != NULL); |
2366 | 2365 |
2367 __ Push(x0); | 2366 __ Push(x0); |
2368 __ CallRuntime( | 2367 __ CallRuntime((is_strict(language_mode()) |
2369 (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 2368 ? Runtime::kStoreKeyedToSuper_Strict |
2370 : Runtime::kStoreKeyedToSuper_Sloppy), | 2369 : Runtime::kStoreKeyedToSuper_Sloppy)); |
2371 4); | |
2372 } | 2370 } |
2373 | 2371 |
2374 | 2372 |
2375 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2373 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2376 ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment"); | 2374 ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment"); |
2377 // Assignment to a property, using a keyed store IC. | 2375 // Assignment to a property, using a keyed store IC. |
2378 | 2376 |
2379 // TODO(all): Could we pass this in registers rather than on the stack? | 2377 // TODO(all): Could we pass this in registers rather than on the stack? |
2380 __ Pop(StoreDescriptor::NameRegister(), StoreDescriptor::ReceiverRegister()); | 2378 __ Pop(StoreDescriptor::NameRegister(), StoreDescriptor::ReceiverRegister()); |
2381 DCHECK(StoreDescriptor::ValueRegister().is(x0)); | 2379 DCHECK(StoreDescriptor::ValueRegister().is(x0)); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2493 __ Push(x0, scratch); | 2491 __ Push(x0, scratch); |
2494 __ Push(key->value()); | 2492 __ Push(key->value()); |
2495 __ Push(Smi::FromInt(language_mode())); | 2493 __ Push(Smi::FromInt(language_mode())); |
2496 | 2494 |
2497 // Stack here: | 2495 // Stack here: |
2498 // - home_object | 2496 // - home_object |
2499 // - this (receiver) | 2497 // - this (receiver) |
2500 // - this (receiver) <-- LoadFromSuper will pop here and below. | 2498 // - this (receiver) <-- LoadFromSuper will pop here and below. |
2501 // - home_object | 2499 // - home_object |
2502 // - language_mode | 2500 // - language_mode |
2503 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2501 __ CallRuntime(Runtime::kLoadFromSuper); |
2504 | 2502 |
2505 // Replace home_object with target function. | 2503 // Replace home_object with target function. |
2506 __ Poke(x0, kPointerSize); | 2504 __ Poke(x0, kPointerSize); |
2507 | 2505 |
2508 // Stack here: | 2506 // Stack here: |
2509 // - target function | 2507 // - target function |
2510 // - this (receiver) | 2508 // - this (receiver) |
2511 EmitCall(expr); | 2509 EmitCall(expr); |
2512 } | 2510 } |
2513 | 2511 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2554 VisitForStackValue(prop->key()); | 2552 VisitForStackValue(prop->key()); |
2555 __ Push(Smi::FromInt(language_mode())); | 2553 __ Push(Smi::FromInt(language_mode())); |
2556 | 2554 |
2557 // Stack here: | 2555 // Stack here: |
2558 // - home_object | 2556 // - home_object |
2559 // - this (receiver) | 2557 // - this (receiver) |
2560 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. | 2558 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. |
2561 // - home_object | 2559 // - home_object |
2562 // - key | 2560 // - key |
2563 // - language_mode | 2561 // - language_mode |
2564 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2562 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
2565 | 2563 |
2566 // Replace home_object with target function. | 2564 // Replace home_object with target function. |
2567 __ Poke(x0, kPointerSize); | 2565 __ Poke(x0, kPointerSize); |
2568 | 2566 |
2569 // Stack here: | 2567 // Stack here: |
2570 // - target function | 2568 // - target function |
2571 // - this (receiver) | 2569 // - this (receiver) |
2572 EmitCall(expr); | 2570 EmitCall(expr); |
2573 } | 2571 } |
2574 | 2572 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2612 | 2610 |
2613 // Prepare to push the language mode. | 2611 // Prepare to push the language mode. |
2614 __ Mov(x11, Smi::FromInt(language_mode())); | 2612 __ Mov(x11, Smi::FromInt(language_mode())); |
2615 // Prepare to push the start position of the scope the calls resides in. | 2613 // Prepare to push the start position of the scope the calls resides in. |
2616 __ Mov(x12, Smi::FromInt(scope()->start_position())); | 2614 __ Mov(x12, Smi::FromInt(scope()->start_position())); |
2617 | 2615 |
2618 // Push. | 2616 // Push. |
2619 __ Push(x9, x10, x11, x12); | 2617 __ Push(x9, x10, x11, x12); |
2620 | 2618 |
2621 // Do the runtime call. | 2619 // Do the runtime call. |
2622 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2620 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); |
2623 } | 2621 } |
2624 | 2622 |
2625 | 2623 |
2626 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | 2624 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. |
2627 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | 2625 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
2628 VariableProxy* callee = expr->expression()->AsVariableProxy(); | 2626 VariableProxy* callee = expr->expression()->AsVariableProxy(); |
2629 if (callee->var()->IsLookupSlot()) { | 2627 if (callee->var()->IsLookupSlot()) { |
2630 Label slow, done; | 2628 Label slow, done; |
2631 SetExpressionPosition(callee); | 2629 SetExpressionPosition(callee); |
2632 // Generate code for loading from variables potentially shadowed | 2630 // Generate code for loading from variables potentially shadowed |
2633 // by eval-introduced variables. | 2631 // by eval-introduced variables. |
2634 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | 2632 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |
2635 | 2633 |
2636 __ Bind(&slow); | 2634 __ Bind(&slow); |
2637 // Call the runtime to find the function to call (returned in x0) | 2635 // Call the runtime to find the function to call (returned in x0) |
2638 // and the object holding it (returned in x1). | 2636 // and the object holding it (returned in x1). |
2639 __ Mov(x10, Operand(callee->name())); | 2637 __ Mov(x10, Operand(callee->name())); |
2640 __ Push(context_register(), x10); | 2638 __ Push(context_register(), x10); |
2641 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 2639 __ CallRuntime(Runtime::kLoadLookupSlot); |
2642 __ Push(x0, x1); // Receiver, function. | 2640 __ Push(x0, x1); // Receiver, function. |
2643 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); | 2641 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
2644 | 2642 |
2645 // If fast case code has been generated, emit code to push the | 2643 // If fast case code has been generated, emit code to push the |
2646 // function and receiver and have the slow path jump around this | 2644 // function and receiver and have the slow path jump around this |
2647 // code. | 2645 // code. |
2648 if (done.is_linked()) { | 2646 if (done.is_linked()) { |
2649 Label call; | 2647 Label call; |
2650 __ B(&call); | 2648 __ B(&call); |
2651 __ Bind(&done); | 2649 __ Bind(&done); |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3274 ZoneList<Expression*>* args = expr->arguments(); | 3272 ZoneList<Expression*>* args = expr->arguments(); |
3275 DCHECK_EQ(1, args->length()); | 3273 DCHECK_EQ(1, args->length()); |
3276 | 3274 |
3277 // Load the argument into x0 and convert it. | 3275 // Load the argument into x0 and convert it. |
3278 VisitForAccumulatorValue(args->at(0)); | 3276 VisitForAccumulatorValue(args->at(0)); |
3279 | 3277 |
3280 // Convert the object to an integer. | 3278 // Convert the object to an integer. |
3281 Label done_convert; | 3279 Label done_convert; |
3282 __ JumpIfSmi(x0, &done_convert); | 3280 __ JumpIfSmi(x0, &done_convert); |
3283 __ Push(x0); | 3281 __ Push(x0); |
3284 __ CallRuntime(Runtime::kToInteger, 1); | 3282 __ CallRuntime(Runtime::kToInteger); |
3285 __ bind(&done_convert); | 3283 __ bind(&done_convert); |
3286 context()->Plug(x0); | 3284 context()->Plug(x0); |
3287 } | 3285 } |
3288 | 3286 |
3289 | 3287 |
3290 void FullCodeGenerator::EmitToName(CallRuntime* expr) { | 3288 void FullCodeGenerator::EmitToName(CallRuntime* expr) { |
3291 ZoneList<Expression*>* args = expr->arguments(); | 3289 ZoneList<Expression*>* args = expr->arguments(); |
3292 DCHECK_EQ(1, args->length()); | 3290 DCHECK_EQ(1, args->length()); |
3293 | 3291 |
3294 // Load the argument into x0 and convert it. | 3292 // Load the argument into x0 and convert it. |
3295 VisitForAccumulatorValue(args->at(0)); | 3293 VisitForAccumulatorValue(args->at(0)); |
3296 | 3294 |
3297 Label convert, done_convert; | 3295 Label convert, done_convert; |
3298 __ JumpIfSmi(x0, &convert); | 3296 __ JumpIfSmi(x0, &convert); |
3299 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); | 3297 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); |
3300 __ JumpIfObjectType(x0, x1, x1, LAST_NAME_TYPE, &done_convert, ls); | 3298 __ JumpIfObjectType(x0, x1, x1, LAST_NAME_TYPE, &done_convert, ls); |
3301 __ Bind(&convert); | 3299 __ Bind(&convert); |
3302 __ Push(x0); | 3300 __ Push(x0); |
3303 __ CallRuntime(Runtime::kToName, 1); | 3301 __ CallRuntime(Runtime::kToName); |
3304 __ Bind(&done_convert); | 3302 __ Bind(&done_convert); |
3305 context()->Plug(x0); | 3303 context()->Plug(x0); |
3306 } | 3304 } |
3307 | 3305 |
3308 | 3306 |
3309 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3307 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
3310 ZoneList<Expression*>* args = expr->arguments(); | 3308 ZoneList<Expression*>* args = expr->arguments(); |
3311 DCHECK(args->length() == 1); | 3309 DCHECK(args->length() == 1); |
3312 | 3310 |
3313 VisitForAccumulatorValue(args->at(0)); | 3311 VisitForAccumulatorValue(args->at(0)); |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3743 __ ObjectUntag(untagged_result, result); | 3741 __ ObjectUntag(untagged_result, result); |
3744 __ Str(map_reg, MemOperand(untagged_result, HeapObject::kMapOffset)); | 3742 __ Str(map_reg, MemOperand(untagged_result, HeapObject::kMapOffset)); |
3745 __ Stp(empty_fixed_array, empty_fixed_array, | 3743 __ Stp(empty_fixed_array, empty_fixed_array, |
3746 MemOperand(untagged_result, JSObject::kPropertiesOffset)); | 3744 MemOperand(untagged_result, JSObject::kPropertiesOffset)); |
3747 __ Stp(result_value, boolean_done, | 3745 __ Stp(result_value, boolean_done, |
3748 MemOperand(untagged_result, JSIteratorResult::kValueOffset)); | 3746 MemOperand(untagged_result, JSIteratorResult::kValueOffset)); |
3749 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 3747 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
3750 __ B(&done); | 3748 __ B(&done); |
3751 | 3749 |
3752 __ Bind(&runtime); | 3750 __ Bind(&runtime); |
3753 __ CallRuntime(Runtime::kCreateIterResultObject, 2); | 3751 __ CallRuntime(Runtime::kCreateIterResultObject); |
3754 | 3752 |
3755 __ Bind(&done); | 3753 __ Bind(&done); |
3756 context()->Plug(x0); | 3754 context()->Plug(x0); |
3757 } | 3755 } |
3758 | 3756 |
3759 | 3757 |
3760 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 3758 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
3761 // Push undefined as the receiver. | 3759 // Push undefined as the receiver. |
3762 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 3760 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
3763 __ Push(x0); | 3761 __ Push(x0); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3834 case Token::DELETE: { | 3832 case Token::DELETE: { |
3835 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3833 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
3836 Property* property = expr->expression()->AsProperty(); | 3834 Property* property = expr->expression()->AsProperty(); |
3837 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3835 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
3838 | 3836 |
3839 if (property != NULL) { | 3837 if (property != NULL) { |
3840 VisitForStackValue(property->obj()); | 3838 VisitForStackValue(property->obj()); |
3841 VisitForStackValue(property->key()); | 3839 VisitForStackValue(property->key()); |
3842 __ CallRuntime(is_strict(language_mode()) | 3840 __ CallRuntime(is_strict(language_mode()) |
3843 ? Runtime::kDeleteProperty_Strict | 3841 ? Runtime::kDeleteProperty_Strict |
3844 : Runtime::kDeleteProperty_Sloppy, | 3842 : Runtime::kDeleteProperty_Sloppy); |
3845 2); | |
3846 context()->Plug(x0); | 3843 context()->Plug(x0); |
3847 } else if (proxy != NULL) { | 3844 } else if (proxy != NULL) { |
3848 Variable* var = proxy->var(); | 3845 Variable* var = proxy->var(); |
3849 // Delete of an unqualified identifier is disallowed in strict mode but | 3846 // Delete of an unqualified identifier is disallowed in strict mode but |
3850 // "delete this" is allowed. | 3847 // "delete this" is allowed. |
3851 bool is_this = var->HasThisName(isolate()); | 3848 bool is_this = var->HasThisName(isolate()); |
3852 DCHECK(is_sloppy(language_mode()) || is_this); | 3849 DCHECK(is_sloppy(language_mode()) || is_this); |
3853 if (var->IsUnallocatedOrGlobalSlot()) { | 3850 if (var->IsUnallocatedOrGlobalSlot()) { |
3854 __ LoadGlobalObject(x12); | 3851 __ LoadGlobalObject(x12); |
3855 __ Mov(x11, Operand(var->name())); | 3852 __ Mov(x11, Operand(var->name())); |
3856 __ Push(x12, x11); | 3853 __ Push(x12, x11); |
3857 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); | 3854 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
3858 context()->Plug(x0); | 3855 context()->Plug(x0); |
3859 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 3856 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
3860 // Result of deleting non-global, non-dynamic variables is false. | 3857 // Result of deleting non-global, non-dynamic variables is false. |
3861 // The subexpression does not have side effects. | 3858 // The subexpression does not have side effects. |
3862 context()->Plug(is_this); | 3859 context()->Plug(is_this); |
3863 } else { | 3860 } else { |
3864 // Non-global variable. Call the runtime to try to delete from the | 3861 // Non-global variable. Call the runtime to try to delete from the |
3865 // context where the variable was introduced. | 3862 // context where the variable was introduced. |
3866 __ Mov(x2, Operand(var->name())); | 3863 __ Mov(x2, Operand(var->name())); |
3867 __ Push(context_register(), x2); | 3864 __ Push(context_register(), x2); |
3868 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); | 3865 __ CallRuntime(Runtime::kDeleteLookupSlot); |
3869 context()->Plug(x0); | 3866 context()->Plug(x0); |
3870 } | 3867 } |
3871 } else { | 3868 } else { |
3872 // Result of deleting non-property, non-variable reference is true. | 3869 // Result of deleting non-property, non-variable reference is true. |
3873 // The subexpression may have side effects. | 3870 // The subexpression may have side effects. |
3874 VisitForEffect(expr->expression()); | 3871 VisitForEffect(expr->expression()); |
3875 context()->Plug(true); | 3872 context()->Plug(true); |
3876 } | 3873 } |
3877 break; | 3874 break; |
3878 break; | 3875 break; |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4297 Label* if_false = NULL; | 4294 Label* if_false = NULL; |
4298 Label* fall_through = NULL; | 4295 Label* fall_through = NULL; |
4299 context()->PrepareTest(&materialize_true, &materialize_false, | 4296 context()->PrepareTest(&materialize_true, &materialize_false, |
4300 &if_true, &if_false, &fall_through); | 4297 &if_true, &if_false, &fall_through); |
4301 | 4298 |
4302 Token::Value op = expr->op(); | 4299 Token::Value op = expr->op(); |
4303 VisitForStackValue(expr->left()); | 4300 VisitForStackValue(expr->left()); |
4304 switch (op) { | 4301 switch (op) { |
4305 case Token::IN: | 4302 case Token::IN: |
4306 VisitForStackValue(expr->right()); | 4303 VisitForStackValue(expr->right()); |
4307 __ CallRuntime(Runtime::kHasProperty, 2); | 4304 __ CallRuntime(Runtime::kHasProperty); |
4308 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 4305 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
4309 __ CompareRoot(x0, Heap::kTrueValueRootIndex); | 4306 __ CompareRoot(x0, Heap::kTrueValueRootIndex); |
4310 Split(eq, if_true, if_false, fall_through); | 4307 Split(eq, if_true, if_false, fall_through); |
4311 break; | 4308 break; |
4312 | 4309 |
4313 case Token::INSTANCEOF: { | 4310 case Token::INSTANCEOF: { |
4314 VisitForAccumulatorValue(expr->right()); | 4311 VisitForAccumulatorValue(expr->right()); |
4315 __ Pop(x1); | 4312 __ Pop(x1); |
4316 InstanceOfStub stub(isolate()); | 4313 InstanceOfStub stub(isolate()); |
4317 __ CallStub(&stub); | 4314 __ CallStub(&stub); |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4644 | 4641 |
4645 __ Bind(&slow_resume); | 4642 __ Bind(&slow_resume); |
4646 } | 4643 } |
4647 | 4644 |
4648 // Otherwise, we push holes for the operand stack and call the runtime to fix | 4645 // Otherwise, we push holes for the operand stack and call the runtime to fix |
4649 // up the stack and the handlers. | 4646 // up the stack and the handlers. |
4650 __ PushMultipleTimes(the_hole, operand_stack_size); | 4647 __ PushMultipleTimes(the_hole, operand_stack_size); |
4651 | 4648 |
4652 __ Mov(x10, Smi::FromInt(resume_mode)); | 4649 __ Mov(x10, Smi::FromInt(resume_mode)); |
4653 __ Push(generator_object, result_register(), x10); | 4650 __ Push(generator_object, result_register(), x10); |
4654 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 4651 __ CallRuntime(Runtime::kResumeJSGeneratorObject); |
4655 // Not reached: the runtime call returns elsewhere. | 4652 // Not reached: the runtime call returns elsewhere. |
4656 __ Unreachable(); | 4653 __ Unreachable(); |
4657 | 4654 |
4658 __ Bind(&done); | 4655 __ Bind(&done); |
4659 context()->Plug(result_register()); | 4656 context()->Plug(result_register()); |
4660 } | 4657 } |
4661 | 4658 |
4662 | 4659 |
4663 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 4660 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
4664 Label allocate, done_allocate; | 4661 Label allocate, done_allocate; |
4665 | 4662 |
4666 // Allocate and populate an object with this form: { value: VAL, done: DONE } | 4663 // Allocate and populate an object with this form: { value: VAL, done: DONE } |
4667 | 4664 |
4668 Register result = x0; | 4665 Register result = x0; |
4669 __ Allocate(JSIteratorResult::kSize, result, x10, x11, &allocate, TAG_OBJECT); | 4666 __ Allocate(JSIteratorResult::kSize, result, x10, x11, &allocate, TAG_OBJECT); |
4670 __ B(&done_allocate); | 4667 __ B(&done_allocate); |
4671 | 4668 |
4672 __ Bind(&allocate); | 4669 __ Bind(&allocate); |
4673 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 4670 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
4674 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 4671 __ CallRuntime(Runtime::kAllocateInNewSpace); |
4675 | 4672 |
4676 __ Bind(&done_allocate); | 4673 __ Bind(&done_allocate); |
4677 Register map_reg = x1; | 4674 Register map_reg = x1; |
4678 Register result_value = x2; | 4675 Register result_value = x2; |
4679 Register boolean_done = x3; | 4676 Register boolean_done = x3; |
4680 Register empty_fixed_array = x4; | 4677 Register empty_fixed_array = x4; |
4681 Register untagged_result = x5; | 4678 Register untagged_result = x5; |
4682 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, map_reg); | 4679 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, map_reg); |
4683 __ Pop(result_value); | 4680 __ Pop(result_value); |
4684 __ LoadRoot(boolean_done, | 4681 __ LoadRoot(boolean_done, |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4895 } | 4892 } |
4896 | 4893 |
4897 return INTERRUPT; | 4894 return INTERRUPT; |
4898 } | 4895 } |
4899 | 4896 |
4900 | 4897 |
4901 } // namespace internal | 4898 } // namespace internal |
4902 } // namespace v8 | 4899 } // namespace v8 |
4903 | 4900 |
4904 #endif // V8_TARGET_ARCH_ARM64 | 4901 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |