| 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 |