| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_PPC | 5 #if V8_TARGET_ARCH_PPC |
| 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 int locals_count = info->scope()->num_stack_slots(); | 142 int locals_count = info->scope()->num_stack_slots(); |
| 143 // Generators allocate locals, if any, in context slots. | 143 // Generators allocate locals, if any, in context slots. |
| 144 DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); | 144 DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); |
| 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 __ Add(ip, sp, -(locals_count * kPointerSize), r0); | 148 __ Add(ip, sp, -(locals_count * kPointerSize), r0); |
| 149 __ LoadRoot(r5, Heap::kRealStackLimitRootIndex); | 149 __ LoadRoot(r5, Heap::kRealStackLimitRootIndex); |
| 150 __ cmpl(ip, r5); | 150 __ cmpl(ip, r5); |
| 151 __ bc_short(ge, &ok); | 151 __ bc_short(ge, &ok); |
| 152 __ CallRuntime(Runtime::kThrowStackOverflow, 0); | 152 __ CallRuntime(Runtime::kThrowStackOverflow); |
| 153 __ bind(&ok); | 153 __ bind(&ok); |
| 154 } | 154 } |
| 155 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 155 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 156 int kMaxPushes = FLAG_optimize_for_size ? 4 : 32; | 156 int kMaxPushes = FLAG_optimize_for_size ? 4 : 32; |
| 157 if (locals_count >= kMaxPushes) { | 157 if (locals_count >= kMaxPushes) { |
| 158 int loop_iterations = locals_count / kMaxPushes; | 158 int loop_iterations = locals_count / kMaxPushes; |
| 159 __ mov(r5, Operand(loop_iterations)); | 159 __ mov(r5, Operand(loop_iterations)); |
| 160 __ mtctr(r5); | 160 __ mtctr(r5); |
| 161 Label loop_header; | 161 Label loop_header; |
| 162 __ bind(&loop_header); | 162 __ bind(&loop_header); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 179 | 179 |
| 180 // Possibly allocate a local context. | 180 // Possibly allocate a local context. |
| 181 if (info->scope()->num_heap_slots() > 0) { | 181 if (info->scope()->num_heap_slots() > 0) { |
| 182 // Argument to NewContext is the function, which is still in r4. | 182 // Argument to NewContext is the function, which is still in r4. |
| 183 Comment cmnt(masm_, "[ Allocate context"); | 183 Comment cmnt(masm_, "[ Allocate context"); |
| 184 bool need_write_barrier = true; | 184 bool need_write_barrier = true; |
| 185 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 185 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 186 if (info->scope()->is_script_scope()) { | 186 if (info->scope()->is_script_scope()) { |
| 187 __ push(r4); | 187 __ push(r4); |
| 188 __ Push(info->scope()->GetScopeInfo(info->isolate())); | 188 __ Push(info->scope()->GetScopeInfo(info->isolate())); |
| 189 __ CallRuntime(Runtime::kNewScriptContext, 2); | 189 __ CallRuntime(Runtime::kNewScriptContext); |
| 190 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); | 190 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); |
| 191 // The new target value is not used, clobbering is safe. | 191 // The new target value is not used, clobbering is safe. |
| 192 DCHECK_NULL(info->scope()->new_target_var()); | 192 DCHECK_NULL(info->scope()->new_target_var()); |
| 193 } else { | 193 } else { |
| 194 if (info->scope()->new_target_var() != nullptr) { | 194 if (info->scope()->new_target_var() != nullptr) { |
| 195 __ push(r6); // Preserve new target. | 195 __ push(r6); // Preserve new target. |
| 196 } | 196 } |
| 197 if (slots <= FastNewContextStub::kMaximumSlots) { | 197 if (slots <= FastNewContextStub::kMaximumSlots) { |
| 198 FastNewContextStub stub(isolate(), slots); | 198 FastNewContextStub stub(isolate(), slots); |
| 199 __ CallStub(&stub); | 199 __ CallStub(&stub); |
| 200 // Result of FastNewContextStub is always in new space. | 200 // Result of FastNewContextStub is always in new space. |
| 201 need_write_barrier = false; | 201 need_write_barrier = false; |
| 202 } else { | 202 } else { |
| 203 __ push(r4); | 203 __ push(r4); |
| 204 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 204 __ CallRuntime(Runtime::kNewFunctionContext); |
| 205 } | 205 } |
| 206 if (info->scope()->new_target_var() != nullptr) { | 206 if (info->scope()->new_target_var() != nullptr) { |
| 207 __ pop(r6); // Preserve new target. | 207 __ pop(r6); // Preserve new target. |
| 208 } | 208 } |
| 209 } | 209 } |
| 210 function_in_register_r4 = false; | 210 function_in_register_r4 = false; |
| 211 // Context is returned in r3. It replaces the context passed to us. | 211 // Context is returned in r3. It replaces the context passed to us. |
| 212 // It's saved in the stack and kept live in cp. | 212 // It's saved in the stack and kept live in cp. |
| 213 __ mr(cp, r3); | 213 __ mr(cp, r3); |
| 214 __ StoreP(r3, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 214 __ StoreP(r3, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); | 310 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); |
| 311 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( | 311 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( |
| 312 is_unmapped, literal()->has_duplicate_parameters()); | 312 is_unmapped, literal()->has_duplicate_parameters()); |
| 313 ArgumentsAccessStub stub(isolate(), type); | 313 ArgumentsAccessStub stub(isolate(), type); |
| 314 __ CallStub(&stub); | 314 __ CallStub(&stub); |
| 315 | 315 |
| 316 SetVar(arguments, r3, r4, r5); | 316 SetVar(arguments, r3, r4, r5); |
| 317 } | 317 } |
| 318 | 318 |
| 319 if (FLAG_trace) { | 319 if (FLAG_trace) { |
| 320 __ CallRuntime(Runtime::kTraceEnter, 0); | 320 __ CallRuntime(Runtime::kTraceEnter); |
| 321 } | 321 } |
| 322 | 322 |
| 323 // Visit the declarations and body unless there is an illegal | 323 // Visit the declarations and body unless there is an illegal |
| 324 // redeclaration. | 324 // redeclaration. |
| 325 if (scope()->HasIllegalRedeclaration()) { | 325 if (scope()->HasIllegalRedeclaration()) { |
| 326 Comment cmnt(masm_, "[ Declarations"); | 326 Comment cmnt(masm_, "[ Declarations"); |
| 327 VisitForEffect(scope()->GetIllegalRedeclaration()); | 327 VisitForEffect(scope()->GetIllegalRedeclaration()); |
| 328 | 328 |
| 329 } else { | 329 } else { |
| 330 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 330 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 void FullCodeGenerator::EmitReturnSequence() { | 429 void FullCodeGenerator::EmitReturnSequence() { |
| 430 Comment cmnt(masm_, "[ Return sequence"); | 430 Comment cmnt(masm_, "[ Return sequence"); |
| 431 if (return_label_.is_bound()) { | 431 if (return_label_.is_bound()) { |
| 432 __ b(&return_label_); | 432 __ b(&return_label_); |
| 433 } else { | 433 } else { |
| 434 __ bind(&return_label_); | 434 __ bind(&return_label_); |
| 435 if (FLAG_trace) { | 435 if (FLAG_trace) { |
| 436 // Push the return value on the stack as the parameter. | 436 // Push the return value on the stack as the parameter. |
| 437 // Runtime::TraceExit returns its parameter in r3 | 437 // Runtime::TraceExit returns its parameter in r3 |
| 438 __ push(r3); | 438 __ push(r3); |
| 439 __ CallRuntime(Runtime::kTraceExit, 1); | 439 __ CallRuntime(Runtime::kTraceExit); |
| 440 } | 440 } |
| 441 // Pretend that the exit is a backwards jump to the entry. | 441 // Pretend that the exit is a backwards jump to the entry. |
| 442 int weight = 1; | 442 int weight = 1; |
| 443 if (info_->ShouldSelfOptimize()) { | 443 if (info_->ShouldSelfOptimize()) { |
| 444 weight = FLAG_interrupt_budget / FLAG_self_opt_count; | 444 weight = FLAG_interrupt_budget / FLAG_self_opt_count; |
| 445 } else { | 445 } else { |
| 446 int distance = masm_->pc_offset() + kCodeSizeMultiplier / 2; | 446 int distance = masm_->pc_offset() + kCodeSizeMultiplier / 2; |
| 447 weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier)); | 447 weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier)); |
| 448 } | 448 } |
| 449 EmitProfilingCounterDecrement(weight); | 449 EmitProfilingCounterDecrement(weight); |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 // Note: For variables we must not push an initial value (such as | 808 // Note: For variables we must not push an initial value (such as |
| 809 // 'undefined') because we may have a (legal) redeclaration and we | 809 // 'undefined') because we may have a (legal) redeclaration and we |
| 810 // must not destroy the current value. | 810 // must not destroy the current value. |
| 811 if (hole_init) { | 811 if (hole_init) { |
| 812 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); | 812 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); |
| 813 } else { | 813 } else { |
| 814 __ LoadSmiLiteral(r3, Smi::FromInt(0)); // Indicates no initial value. | 814 __ LoadSmiLiteral(r3, Smi::FromInt(0)); // Indicates no initial value. |
| 815 } | 815 } |
| 816 __ Push(r5, r3); | 816 __ Push(r5, r3); |
| 817 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); | 817 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
| 818 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 818 __ CallRuntime(Runtime::kDeclareLookupSlot); |
| 819 break; | 819 break; |
| 820 } | 820 } |
| 821 } | 821 } |
| 822 } | 822 } |
| 823 | 823 |
| 824 | 824 |
| 825 void FullCodeGenerator::VisitFunctionDeclaration( | 825 void FullCodeGenerator::VisitFunctionDeclaration( |
| 826 FunctionDeclaration* declaration) { | 826 FunctionDeclaration* declaration) { |
| 827 VariableProxy* proxy = declaration->proxy(); | 827 VariableProxy* proxy = declaration->proxy(); |
| 828 Variable* variable = proxy->var(); | 828 Variable* variable = proxy->var(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 break; | 861 break; |
| 862 } | 862 } |
| 863 | 863 |
| 864 case VariableLocation::LOOKUP: { | 864 case VariableLocation::LOOKUP: { |
| 865 Comment cmnt(masm_, "[ FunctionDeclaration"); | 865 Comment cmnt(masm_, "[ FunctionDeclaration"); |
| 866 __ mov(r5, Operand(variable->name())); | 866 __ mov(r5, Operand(variable->name())); |
| 867 __ Push(r5); | 867 __ Push(r5); |
| 868 // Push initial value for function declaration. | 868 // Push initial value for function declaration. |
| 869 VisitForStackValue(declaration->fun()); | 869 VisitForStackValue(declaration->fun()); |
| 870 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); | 870 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
| 871 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 871 __ CallRuntime(Runtime::kDeclareLookupSlot); |
| 872 break; | 872 break; |
| 873 } | 873 } |
| 874 } | 874 } |
| 875 } | 875 } |
| 876 | 876 |
| 877 | 877 |
| 878 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 878 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 879 // Call the runtime to declare the globals. | 879 // Call the runtime to declare the globals. |
| 880 __ mov(r4, Operand(pairs)); | 880 __ mov(r4, Operand(pairs)); |
| 881 __ LoadSmiLiteral(r3, Smi::FromInt(DeclareGlobalsFlags())); | 881 __ LoadSmiLiteral(r3, Smi::FromInt(DeclareGlobalsFlags())); |
| 882 __ Push(r4, r3); | 882 __ Push(r4, r3); |
| 883 __ CallRuntime(Runtime::kDeclareGlobals, 2); | 883 __ CallRuntime(Runtime::kDeclareGlobals); |
| 884 // Return value is ignored. | 884 // Return value is ignored. |
| 885 } | 885 } |
| 886 | 886 |
| 887 | 887 |
| 888 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 888 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
| 889 // Call the runtime to declare the modules. | 889 // Call the runtime to declare the modules. |
| 890 __ Push(descriptions); | 890 __ Push(descriptions); |
| 891 __ CallRuntime(Runtime::kDeclareModules, 1); | 891 __ CallRuntime(Runtime::kDeclareModules); |
| 892 // Return value is ignored. | 892 // Return value is ignored. |
| 893 } | 893 } |
| 894 | 894 |
| 895 | 895 |
| 896 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 896 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 897 Comment cmnt(masm_, "[ SwitchStatement"); | 897 Comment cmnt(masm_, "[ SwitchStatement"); |
| 898 Breakable nested_statement(this, stmt); | 898 Breakable nested_statement(this, stmt); |
| 899 SetStatementPosition(stmt); | 899 SetStatementPosition(stmt); |
| 900 | 900 |
| 901 // Keep the switch value on the stack until a case matches. | 901 // Keep the switch value on the stack until a case matches. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1036 | 1036 |
| 1037 // The enum cache is valid. Load the map of the object being | 1037 // The enum cache is valid. Load the map of the object being |
| 1038 // iterated over and use the cache for the iteration. | 1038 // iterated over and use the cache for the iteration. |
| 1039 Label use_cache; | 1039 Label use_cache; |
| 1040 __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset)); | 1040 __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| 1041 __ b(&use_cache); | 1041 __ b(&use_cache); |
| 1042 | 1042 |
| 1043 // Get the set of properties to enumerate. | 1043 // Get the set of properties to enumerate. |
| 1044 __ bind(&call_runtime); | 1044 __ bind(&call_runtime); |
| 1045 __ push(r3); // Duplicate the enumerable object on the stack. | 1045 __ push(r3); // Duplicate the enumerable object on the stack. |
| 1046 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 1046 __ CallRuntime(Runtime::kGetPropertyNamesFast); |
| 1047 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); | 1047 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); |
| 1048 | 1048 |
| 1049 // If we got a map from the runtime call, we can do a fast | 1049 // If we got a map from the runtime call, we can do a fast |
| 1050 // modification check. Otherwise, we got a fixed array, and we have | 1050 // modification check. Otherwise, we got a fixed array, and we have |
| 1051 // to do a slow check. | 1051 // to do a slow check. |
| 1052 Label fixed_array; | 1052 Label fixed_array; |
| 1053 __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset)); | 1053 __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| 1054 __ LoadRoot(ip, Heap::kMetaMapRootIndex); | 1054 __ LoadRoot(ip, Heap::kMetaMapRootIndex); |
| 1055 __ cmp(r5, ip); | 1055 __ cmp(r5, ip); |
| 1056 __ bne(&fixed_array); | 1056 __ bne(&fixed_array); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1118 Label update_each; | 1118 Label update_each; |
| 1119 __ LoadP(r4, MemOperand(sp, 4 * kPointerSize)); | 1119 __ LoadP(r4, MemOperand(sp, 4 * kPointerSize)); |
| 1120 __ LoadP(r7, FieldMemOperand(r4, HeapObject::kMapOffset)); | 1120 __ LoadP(r7, FieldMemOperand(r4, HeapObject::kMapOffset)); |
| 1121 __ cmp(r7, r5); | 1121 __ cmp(r7, r5); |
| 1122 __ beq(&update_each); | 1122 __ beq(&update_each); |
| 1123 | 1123 |
| 1124 // Convert the entry to a string or (smi) 0 if it isn't a property | 1124 // Convert the entry to a string or (smi) 0 if it isn't a property |
| 1125 // any more. If the property has been removed while iterating, we | 1125 // any more. If the property has been removed while iterating, we |
| 1126 // just skip it. | 1126 // just skip it. |
| 1127 __ Push(r4, r6); // Enumerable and current entry. | 1127 __ Push(r4, r6); // Enumerable and current entry. |
| 1128 __ CallRuntime(Runtime::kForInFilter, 2); | 1128 __ CallRuntime(Runtime::kForInFilter); |
| 1129 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); | 1129 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); |
| 1130 __ mr(r6, r3); | 1130 __ mr(r6, r3); |
| 1131 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 1131 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 1132 __ cmp(r3, r0); | 1132 __ cmp(r3, r0); |
| 1133 __ beq(loop_statement.continue_label()); | 1133 __ beq(loop_statement.continue_label()); |
| 1134 | 1134 |
| 1135 // Update the 'each' property or variable from the possibly filtered | 1135 // Update the 'each' property or variable from the possibly filtered |
| 1136 // entry in register r6. | 1136 // entry in register r6. |
| 1137 __ bind(&update_each); | 1137 __ bind(&update_each); |
| 1138 __ mr(result_register(), r6); | 1138 __ mr(result_register(), r6); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1177 // flag, we need to use the runtime function so that the new function | 1177 // flag, we need to use the runtime function so that the new function |
| 1178 // we are creating here gets a chance to have its code optimized and | 1178 // we are creating here gets a chance to have its code optimized and |
| 1179 // doesn't just get a copy of the existing unoptimized code. | 1179 // doesn't just get a copy of the existing unoptimized code. |
| 1180 if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure && | 1180 if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure && |
| 1181 scope()->is_function_scope() && info->num_literals() == 0) { | 1181 scope()->is_function_scope() && info->num_literals() == 0) { |
| 1182 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); | 1182 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); |
| 1183 __ mov(r5, Operand(info)); | 1183 __ mov(r5, Operand(info)); |
| 1184 __ CallStub(&stub); | 1184 __ CallStub(&stub); |
| 1185 } else { | 1185 } else { |
| 1186 __ Push(info); | 1186 __ Push(info); |
| 1187 __ CallRuntime( | 1187 __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured |
| 1188 pretenure ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure, 1); | 1188 : Runtime::kNewClosure); |
| 1189 } | 1189 } |
| 1190 context()->Plug(r3); | 1190 context()->Plug(r3); |
| 1191 } | 1191 } |
| 1192 | 1192 |
| 1193 | 1193 |
| 1194 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, | 1194 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, |
| 1195 FeedbackVectorSlot slot) { | 1195 FeedbackVectorSlot slot) { |
| 1196 DCHECK(NeedsHomeObject(initializer)); | 1196 DCHECK(NeedsHomeObject(initializer)); |
| 1197 __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); | 1197 __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); |
| 1198 __ mov(StoreDescriptor::NameRegister(), | 1198 __ mov(StoreDescriptor::NameRegister(), |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1317 __ LoadP(r3, ContextSlotOperandCheckExtensions(local, slow)); | 1317 __ LoadP(r3, ContextSlotOperandCheckExtensions(local, slow)); |
| 1318 if (local->mode() == LET || local->mode() == CONST || | 1318 if (local->mode() == LET || local->mode() == CONST || |
| 1319 local->mode() == CONST_LEGACY) { | 1319 local->mode() == CONST_LEGACY) { |
| 1320 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 1320 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 1321 __ bne(done); | 1321 __ bne(done); |
| 1322 if (local->mode() == CONST_LEGACY) { | 1322 if (local->mode() == CONST_LEGACY) { |
| 1323 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); | 1323 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); |
| 1324 } else { // LET || CONST | 1324 } else { // LET || CONST |
| 1325 __ mov(r3, Operand(var->name())); | 1325 __ mov(r3, Operand(var->name())); |
| 1326 __ push(r3); | 1326 __ push(r3); |
| 1327 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1327 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1328 } | 1328 } |
| 1329 } | 1329 } |
| 1330 __ b(done); | 1330 __ b(done); |
| 1331 } | 1331 } |
| 1332 } | 1332 } |
| 1333 | 1333 |
| 1334 | 1334 |
| 1335 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1335 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1336 TypeofMode typeof_mode) { | 1336 TypeofMode typeof_mode) { |
| 1337 Variable* var = proxy->var(); | 1337 Variable* var = proxy->var(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1373 Label done; | 1373 Label done; |
| 1374 // Let and const need a read barrier. | 1374 // Let and const need a read barrier. |
| 1375 GetVar(r3, var); | 1375 GetVar(r3, var); |
| 1376 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 1376 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 1377 __ bne(&done); | 1377 __ bne(&done); |
| 1378 if (var->mode() == LET || var->mode() == CONST) { | 1378 if (var->mode() == LET || var->mode() == CONST) { |
| 1379 // Throw a reference error when using an uninitialized let/const | 1379 // Throw a reference error when using an uninitialized let/const |
| 1380 // binding in harmony mode. | 1380 // binding in harmony mode. |
| 1381 __ mov(r3, Operand(var->name())); | 1381 __ mov(r3, Operand(var->name())); |
| 1382 __ push(r3); | 1382 __ push(r3); |
| 1383 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1383 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1384 } else { | 1384 } else { |
| 1385 // Uninitialized legacy const bindings are unholed. | 1385 // Uninitialized legacy const bindings are unholed. |
| 1386 DCHECK(var->mode() == CONST_LEGACY); | 1386 DCHECK(var->mode() == CONST_LEGACY); |
| 1387 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); | 1387 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); |
| 1388 } | 1388 } |
| 1389 __ bind(&done); | 1389 __ bind(&done); |
| 1390 context()->Plug(r3); | 1390 context()->Plug(r3); |
| 1391 break; | 1391 break; |
| 1392 } | 1392 } |
| 1393 context()->Plug(var); | 1393 context()->Plug(var); |
| 1394 break; | 1394 break; |
| 1395 } | 1395 } |
| 1396 | 1396 |
| 1397 case VariableLocation::LOOKUP: { | 1397 case VariableLocation::LOOKUP: { |
| 1398 Comment cmnt(masm_, "[ Lookup variable"); | 1398 Comment cmnt(masm_, "[ Lookup variable"); |
| 1399 Label done, slow; | 1399 Label done, slow; |
| 1400 // Generate code for loading from variables potentially shadowed | 1400 // Generate code for loading from variables potentially shadowed |
| 1401 // by eval-introduced variables. | 1401 // by eval-introduced variables. |
| 1402 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | 1402 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); |
| 1403 __ bind(&slow); | 1403 __ bind(&slow); |
| 1404 __ mov(r4, Operand(var->name())); | 1404 __ mov(r4, Operand(var->name())); |
| 1405 __ Push(cp, r4); // Context and name. | 1405 __ Push(cp, r4); // Context and name. |
| 1406 Runtime::FunctionId function_id = | 1406 Runtime::FunctionId function_id = |
| 1407 typeof_mode == NOT_INSIDE_TYPEOF | 1407 typeof_mode == NOT_INSIDE_TYPEOF |
| 1408 ? Runtime::kLoadLookupSlot | 1408 ? Runtime::kLoadLookupSlot |
| 1409 : Runtime::kLoadLookupSlotNoReferenceError; | 1409 : Runtime::kLoadLookupSlotNoReferenceError; |
| 1410 __ CallRuntime(function_id, 2); | 1410 __ CallRuntime(function_id); |
| 1411 __ bind(&done); | 1411 __ bind(&done); |
| 1412 context()->Plug(r3); | 1412 context()->Plug(r3); |
| 1413 } | 1413 } |
| 1414 } | 1414 } |
| 1415 } | 1415 } |
| 1416 | 1416 |
| 1417 | 1417 |
| 1418 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1418 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1419 Comment cmnt(masm_, "[ RegExpLiteral"); | 1419 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 1420 __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1420 __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1448 Comment cmnt(masm_, "[ ObjectLiteral"); | 1448 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 1449 | 1449 |
| 1450 Handle<FixedArray> constant_properties = expr->constant_properties(); | 1450 Handle<FixedArray> constant_properties = expr->constant_properties(); |
| 1451 __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1451 __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1452 __ LoadSmiLiteral(r5, Smi::FromInt(expr->literal_index())); | 1452 __ LoadSmiLiteral(r5, Smi::FromInt(expr->literal_index())); |
| 1453 __ mov(r4, Operand(constant_properties)); | 1453 __ mov(r4, Operand(constant_properties)); |
| 1454 int flags = expr->ComputeFlags(); | 1454 int flags = expr->ComputeFlags(); |
| 1455 __ LoadSmiLiteral(r3, Smi::FromInt(flags)); | 1455 __ LoadSmiLiteral(r3, Smi::FromInt(flags)); |
| 1456 if (MustCreateObjectLiteralWithRuntime(expr)) { | 1456 if (MustCreateObjectLiteralWithRuntime(expr)) { |
| 1457 __ Push(r6, r5, r4, r3); | 1457 __ Push(r6, r5, r4, r3); |
| 1458 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1458 __ CallRuntime(Runtime::kCreateObjectLiteral); |
| 1459 } else { | 1459 } else { |
| 1460 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1460 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
| 1461 __ CallStub(&stub); | 1461 __ CallStub(&stub); |
| 1462 } | 1462 } |
| 1463 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1463 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
| 1464 | 1464 |
| 1465 // If result_saved is true the result is on top of the stack. If | 1465 // If result_saved is true the result is on top of the stack. If |
| 1466 // result_saved is false the result is in r3. | 1466 // result_saved is false the result is in r3. |
| 1467 bool result_saved = false; | 1467 bool result_saved = false; |
| 1468 | 1468 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1510 __ LoadP(r3, MemOperand(sp)); | 1510 __ LoadP(r3, MemOperand(sp)); |
| 1511 __ push(r3); | 1511 __ push(r3); |
| 1512 VisitForStackValue(key); | 1512 VisitForStackValue(key); |
| 1513 VisitForStackValue(value); | 1513 VisitForStackValue(value); |
| 1514 if (property->emit_store()) { | 1514 if (property->emit_store()) { |
| 1515 if (NeedsHomeObject(value)) { | 1515 if (NeedsHomeObject(value)) { |
| 1516 EmitSetHomeObject(value, 2, property->GetSlot()); | 1516 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 1517 } | 1517 } |
| 1518 __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); // PropertyAttributes | 1518 __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); // PropertyAttributes |
| 1519 __ push(r3); | 1519 __ push(r3); |
| 1520 __ CallRuntime(Runtime::kSetProperty, 4); | 1520 __ CallRuntime(Runtime::kSetProperty); |
| 1521 } else { | 1521 } else { |
| 1522 __ Drop(3); | 1522 __ Drop(3); |
| 1523 } | 1523 } |
| 1524 break; | 1524 break; |
| 1525 case ObjectLiteral::Property::PROTOTYPE: | 1525 case ObjectLiteral::Property::PROTOTYPE: |
| 1526 // Duplicate receiver on stack. | 1526 // Duplicate receiver on stack. |
| 1527 __ LoadP(r3, MemOperand(sp)); | 1527 __ LoadP(r3, MemOperand(sp)); |
| 1528 __ push(r3); | 1528 __ push(r3); |
| 1529 VisitForStackValue(value); | 1529 VisitForStackValue(value); |
| 1530 DCHECK(property->emit_store()); | 1530 DCHECK(property->emit_store()); |
| 1531 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1531 __ CallRuntime(Runtime::kInternalSetPrototype); |
| 1532 break; | 1532 break; |
| 1533 case ObjectLiteral::Property::GETTER: | 1533 case ObjectLiteral::Property::GETTER: |
| 1534 if (property->emit_store()) { | 1534 if (property->emit_store()) { |
| 1535 accessor_table.lookup(key)->second->getter = property; | 1535 accessor_table.lookup(key)->second->getter = property; |
| 1536 } | 1536 } |
| 1537 break; | 1537 break; |
| 1538 case ObjectLiteral::Property::SETTER: | 1538 case ObjectLiteral::Property::SETTER: |
| 1539 if (property->emit_store()) { | 1539 if (property->emit_store()) { |
| 1540 accessor_table.lookup(key)->second->setter = property; | 1540 accessor_table.lookup(key)->second->setter = property; |
| 1541 } | 1541 } |
| 1542 break; | 1542 break; |
| 1543 } | 1543 } |
| 1544 } | 1544 } |
| 1545 | 1545 |
| 1546 // Emit code to define accessors, using only a single call to the runtime for | 1546 // Emit code to define accessors, using only a single call to the runtime for |
| 1547 // each pair of corresponding getters and setters. | 1547 // each pair of corresponding getters and setters. |
| 1548 for (AccessorTable::Iterator it = accessor_table.begin(); | 1548 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 1549 it != accessor_table.end(); ++it) { | 1549 it != accessor_table.end(); ++it) { |
| 1550 __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. | 1550 __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. |
| 1551 __ push(r3); | 1551 __ push(r3); |
| 1552 VisitForStackValue(it->first); | 1552 VisitForStackValue(it->first); |
| 1553 EmitAccessor(it->second->getter); | 1553 EmitAccessor(it->second->getter); |
| 1554 EmitAccessor(it->second->setter); | 1554 EmitAccessor(it->second->setter); |
| 1555 __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); | 1555 __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); |
| 1556 __ push(r3); | 1556 __ push(r3); |
| 1557 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1557 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); |
| 1558 } | 1558 } |
| 1559 | 1559 |
| 1560 // Object literals have two parts. The "static" part on the left contains no | 1560 // Object literals have two parts. The "static" part on the left contains no |
| 1561 // computed property names, and so we can compute its map ahead of time; see | 1561 // computed property names, and so we can compute its map ahead of time; see |
| 1562 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part | 1562 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
| 1563 // starts with the first computed property name, and continues with all | 1563 // starts with the first computed property name, and continues with all |
| 1564 // properties to its right. All the code from above initializes the static | 1564 // properties to its right. All the code from above initializes the static |
| 1565 // component of the object literal, and arranges for the map of the result to | 1565 // component of the object literal, and arranges for the map of the result to |
| 1566 // reflect the static order in which the keys appear. For the dynamic | 1566 // reflect the static order in which the keys appear. For the dynamic |
| 1567 // properties, we compile them into a series of "SetOwnProperty" runtime | 1567 // properties, we compile them into a series of "SetOwnProperty" runtime |
| 1568 // calls. This will preserve insertion order. | 1568 // calls. This will preserve insertion order. |
| 1569 for (; property_index < expr->properties()->length(); property_index++) { | 1569 for (; property_index < expr->properties()->length(); property_index++) { |
| 1570 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1570 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1571 | 1571 |
| 1572 Expression* value = property->value(); | 1572 Expression* value = property->value(); |
| 1573 if (!result_saved) { | 1573 if (!result_saved) { |
| 1574 __ push(r3); // Save result on the stack | 1574 __ push(r3); // Save result on the stack |
| 1575 result_saved = true; | 1575 result_saved = true; |
| 1576 } | 1576 } |
| 1577 | 1577 |
| 1578 __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. | 1578 __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. |
| 1579 __ push(r3); | 1579 __ push(r3); |
| 1580 | 1580 |
| 1581 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1581 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
| 1582 DCHECK(!property->is_computed_name()); | 1582 DCHECK(!property->is_computed_name()); |
| 1583 VisitForStackValue(value); | 1583 VisitForStackValue(value); |
| 1584 DCHECK(property->emit_store()); | 1584 DCHECK(property->emit_store()); |
| 1585 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1585 __ CallRuntime(Runtime::kInternalSetPrototype); |
| 1586 } else { | 1586 } else { |
| 1587 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); | 1587 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); |
| 1588 VisitForStackValue(value); | 1588 VisitForStackValue(value); |
| 1589 if (NeedsHomeObject(value)) { | 1589 if (NeedsHomeObject(value)) { |
| 1590 EmitSetHomeObject(value, 2, property->GetSlot()); | 1590 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 1591 } | 1591 } |
| 1592 | 1592 |
| 1593 switch (property->kind()) { | 1593 switch (property->kind()) { |
| 1594 case ObjectLiteral::Property::CONSTANT: | 1594 case ObjectLiteral::Property::CONSTANT: |
| 1595 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1595 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1596 case ObjectLiteral::Property::COMPUTED: | 1596 case ObjectLiteral::Property::COMPUTED: |
| 1597 if (property->emit_store()) { | 1597 if (property->emit_store()) { |
| 1598 __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); | 1598 __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); |
| 1599 __ push(r3); | 1599 __ push(r3); |
| 1600 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); | 1600 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked); |
| 1601 } else { | 1601 } else { |
| 1602 __ Drop(3); | 1602 __ Drop(3); |
| 1603 } | 1603 } |
| 1604 break; | 1604 break; |
| 1605 | 1605 |
| 1606 case ObjectLiteral::Property::PROTOTYPE: | 1606 case ObjectLiteral::Property::PROTOTYPE: |
| 1607 UNREACHABLE(); | 1607 UNREACHABLE(); |
| 1608 break; | 1608 break; |
| 1609 | 1609 |
| 1610 case ObjectLiteral::Property::GETTER: | 1610 case ObjectLiteral::Property::GETTER: |
| 1611 __ mov(r3, Operand(Smi::FromInt(NONE))); | 1611 __ mov(r3, Operand(Smi::FromInt(NONE))); |
| 1612 __ push(r3); | 1612 __ push(r3); |
| 1613 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 1613 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
| 1614 break; | 1614 break; |
| 1615 | 1615 |
| 1616 case ObjectLiteral::Property::SETTER: | 1616 case ObjectLiteral::Property::SETTER: |
| 1617 __ mov(r3, Operand(Smi::FromInt(NONE))); | 1617 __ mov(r3, Operand(Smi::FromInt(NONE))); |
| 1618 __ push(r3); | 1618 __ push(r3); |
| 1619 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 1619 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
| 1620 break; | 1620 break; |
| 1621 } | 1621 } |
| 1622 } | 1622 } |
| 1623 } | 1623 } |
| 1624 | 1624 |
| 1625 if (expr->has_function()) { | 1625 if (expr->has_function()) { |
| 1626 DCHECK(result_saved); | 1626 DCHECK(result_saved); |
| 1627 __ LoadP(r3, MemOperand(sp)); | 1627 __ LoadP(r3, MemOperand(sp)); |
| 1628 __ push(r3); | 1628 __ push(r3); |
| 1629 __ CallRuntime(Runtime::kToFastProperties, 1); | 1629 __ CallRuntime(Runtime::kToFastProperties); |
| 1630 } | 1630 } |
| 1631 | 1631 |
| 1632 if (result_saved) { | 1632 if (result_saved) { |
| 1633 context()->PlugTOS(); | 1633 context()->PlugTOS(); |
| 1634 } else { | 1634 } else { |
| 1635 context()->Plug(r3); | 1635 context()->Plug(r3); |
| 1636 } | 1636 } |
| 1637 } | 1637 } |
| 1638 | 1638 |
| 1639 | 1639 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1652 // we can turn it off if we don't have anywhere else to transition to. | 1652 // we can turn it off if we don't have anywhere else to transition to. |
| 1653 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1653 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
| 1654 } | 1654 } |
| 1655 | 1655 |
| 1656 __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1656 __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1657 __ LoadSmiLiteral(r5, Smi::FromInt(expr->literal_index())); | 1657 __ LoadSmiLiteral(r5, Smi::FromInt(expr->literal_index())); |
| 1658 __ mov(r4, Operand(constant_elements)); | 1658 __ mov(r4, Operand(constant_elements)); |
| 1659 if (MustCreateArrayLiteralWithRuntime(expr)) { | 1659 if (MustCreateArrayLiteralWithRuntime(expr)) { |
| 1660 __ LoadSmiLiteral(r3, Smi::FromInt(expr->ComputeFlags())); | 1660 __ LoadSmiLiteral(r3, Smi::FromInt(expr->ComputeFlags())); |
| 1661 __ Push(r6, r5, r4, r3); | 1661 __ Push(r6, r5, r4, r3); |
| 1662 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); | 1662 __ CallRuntime(Runtime::kCreateArrayLiteral); |
| 1663 } else { | 1663 } else { |
| 1664 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1664 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
| 1665 __ CallStub(&stub); | 1665 __ CallStub(&stub); |
| 1666 } | 1666 } |
| 1667 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1667 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
| 1668 | 1668 |
| 1669 bool result_saved = false; // Is the result saved to the stack? | 1669 bool result_saved = false; // Is the result saved to the stack? |
| 1670 ZoneList<Expression*>* subexprs = expr->values(); | 1670 ZoneList<Expression*>* subexprs = expr->values(); |
| 1671 int length = subexprs->length(); | 1671 int length = subexprs->length(); |
| 1672 | 1672 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1709 for (; array_index < length; array_index++) { | 1709 for (; array_index < length; array_index++) { |
| 1710 Expression* subexpr = subexprs->at(array_index); | 1710 Expression* subexpr = subexprs->at(array_index); |
| 1711 | 1711 |
| 1712 __ Push(r3); | 1712 __ Push(r3); |
| 1713 if (subexpr->IsSpread()) { | 1713 if (subexpr->IsSpread()) { |
| 1714 VisitForStackValue(subexpr->AsSpread()->expression()); | 1714 VisitForStackValue(subexpr->AsSpread()->expression()); |
| 1715 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, | 1715 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, |
| 1716 CALL_FUNCTION); | 1716 CALL_FUNCTION); |
| 1717 } else { | 1717 } else { |
| 1718 VisitForStackValue(subexpr); | 1718 VisitForStackValue(subexpr); |
| 1719 __ CallRuntime(Runtime::kAppendElement, 2); | 1719 __ CallRuntime(Runtime::kAppendElement); |
| 1720 } | 1720 } |
| 1721 | 1721 |
| 1722 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); | 1722 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
| 1723 } | 1723 } |
| 1724 | 1724 |
| 1725 if (result_saved) { | 1725 if (result_saved) { |
| 1726 context()->PlugTOS(); | 1726 context()->PlugTOS(); |
| 1727 } else { | 1727 } else { |
| 1728 context()->Plug(r3); | 1728 context()->Plug(r3); |
| 1729 } | 1729 } |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2128 Label operand_loop; | 2128 Label operand_loop; |
| 2129 __ mtctr(r6); | 2129 __ mtctr(r6); |
| 2130 __ bind(&operand_loop); | 2130 __ bind(&operand_loop); |
| 2131 __ push(r5); | 2131 __ push(r5); |
| 2132 __ bdnz(&operand_loop); | 2132 __ bdnz(&operand_loop); |
| 2133 | 2133 |
| 2134 __ bind(&call_resume); | 2134 __ bind(&call_resume); |
| 2135 DCHECK(!result_register().is(r4)); | 2135 DCHECK(!result_register().is(r4)); |
| 2136 __ Push(r4, result_register()); | 2136 __ Push(r4, result_register()); |
| 2137 __ Push(Smi::FromInt(resume_mode)); | 2137 __ Push(Smi::FromInt(resume_mode)); |
| 2138 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2138 __ CallRuntime(Runtime::kResumeJSGeneratorObject); |
| 2139 // Not reached: the runtime call returns elsewhere. | 2139 // Not reached: the runtime call returns elsewhere. |
| 2140 __ stop("not-reached"); | 2140 __ stop("not-reached"); |
| 2141 | 2141 |
| 2142 __ bind(&done); | 2142 __ bind(&done); |
| 2143 context()->Plug(result_register()); | 2143 context()->Plug(result_register()); |
| 2144 } | 2144 } |
| 2145 | 2145 |
| 2146 | 2146 |
| 2147 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2147 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| 2148 Label allocate, done_allocate; | 2148 Label allocate, done_allocate; |
| 2149 | 2149 |
| 2150 __ Allocate(JSIteratorResult::kSize, r3, r5, r6, &allocate, TAG_OBJECT); | 2150 __ Allocate(JSIteratorResult::kSize, r3, r5, r6, &allocate, TAG_OBJECT); |
| 2151 __ b(&done_allocate); | 2151 __ b(&done_allocate); |
| 2152 | 2152 |
| 2153 __ bind(&allocate); | 2153 __ bind(&allocate); |
| 2154 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 2154 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
| 2155 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2155 __ CallRuntime(Runtime::kAllocateInNewSpace); |
| 2156 | 2156 |
| 2157 __ bind(&done_allocate); | 2157 __ bind(&done_allocate); |
| 2158 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r4); | 2158 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r4); |
| 2159 __ pop(r5); | 2159 __ pop(r5); |
| 2160 __ LoadRoot(r6, | 2160 __ LoadRoot(r6, |
| 2161 done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); | 2161 done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); |
| 2162 __ LoadRoot(r7, Heap::kEmptyFixedArrayRootIndex); | 2162 __ LoadRoot(r7, Heap::kEmptyFixedArrayRootIndex); |
| 2163 __ StoreP(r4, FieldMemOperand(r3, HeapObject::kMapOffset), r0); | 2163 __ StoreP(r4, FieldMemOperand(r3, HeapObject::kMapOffset), r0); |
| 2164 __ StoreP(r7, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0); | 2164 __ StoreP(r7, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0); |
| 2165 __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0); | 2165 __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2182 | 2182 |
| 2183 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { | 2183 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
| 2184 // Stack: receiver, home_object. | 2184 // Stack: receiver, home_object. |
| 2185 SetExpressionPosition(prop); | 2185 SetExpressionPosition(prop); |
| 2186 Literal* key = prop->key()->AsLiteral(); | 2186 Literal* key = prop->key()->AsLiteral(); |
| 2187 DCHECK(!key->value()->IsSmi()); | 2187 DCHECK(!key->value()->IsSmi()); |
| 2188 DCHECK(prop->IsSuperAccess()); | 2188 DCHECK(prop->IsSuperAccess()); |
| 2189 | 2189 |
| 2190 __ Push(key->value()); | 2190 __ Push(key->value()); |
| 2191 __ Push(Smi::FromInt(language_mode())); | 2191 __ Push(Smi::FromInt(language_mode())); |
| 2192 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2192 __ CallRuntime(Runtime::kLoadFromSuper); |
| 2193 } | 2193 } |
| 2194 | 2194 |
| 2195 | 2195 |
| 2196 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2196 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2197 SetExpressionPosition(prop); | 2197 SetExpressionPosition(prop); |
| 2198 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); | 2198 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); |
| 2199 __ mov(LoadDescriptor::SlotRegister(), | 2199 __ mov(LoadDescriptor::SlotRegister(), |
| 2200 Operand(SmiFromSlot(prop->PropertyFeedbackSlot()))); | 2200 Operand(SmiFromSlot(prop->PropertyFeedbackSlot()))); |
| 2201 CallIC(ic); | 2201 CallIC(ic); |
| 2202 } | 2202 } |
| 2203 | 2203 |
| 2204 | 2204 |
| 2205 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { | 2205 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
| 2206 // Stack: receiver, home_object, key. | 2206 // Stack: receiver, home_object, key. |
| 2207 SetExpressionPosition(prop); | 2207 SetExpressionPosition(prop); |
| 2208 __ Push(Smi::FromInt(language_mode())); | 2208 __ Push(Smi::FromInt(language_mode())); |
| 2209 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2209 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
| 2210 } | 2210 } |
| 2211 | 2211 |
| 2212 | 2212 |
| 2213 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2213 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2214 Token::Value op, | 2214 Token::Value op, |
| 2215 Expression* left_expr, | 2215 Expression* left_expr, |
| 2216 Expression* right_expr) { | 2216 Expression* right_expr) { |
| 2217 Label done, smi_case, stub_call; | 2217 Label done, smi_case, stub_call; |
| 2218 | 2218 |
| 2219 Register scratch1 = r5; | 2219 Register scratch1 = r5; |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2358 __ LoadP(scratch, MemOperand(sp, 0)); // prototype | 2358 __ LoadP(scratch, MemOperand(sp, 0)); // prototype |
| 2359 } | 2359 } |
| 2360 __ push(scratch); | 2360 __ push(scratch); |
| 2361 EmitPropertyKey(property, lit->GetIdForProperty(i)); | 2361 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
| 2362 | 2362 |
| 2363 // The static prototype property is read only. We handle the non computed | 2363 // The static prototype property is read only. We handle the non computed |
| 2364 // property name case in the parser. Since this is the only case where we | 2364 // property name case in the parser. Since this is the only case where we |
| 2365 // need to check for an own read only property we special case this so we do | 2365 // need to check for an own read only property we special case this so we do |
| 2366 // not need to do this for every property. | 2366 // not need to do this for every property. |
| 2367 if (property->is_static() && property->is_computed_name()) { | 2367 if (property->is_static() && property->is_computed_name()) { |
| 2368 __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1); | 2368 __ CallRuntime(Runtime::kThrowIfStaticPrototype); |
| 2369 __ push(r3); | 2369 __ push(r3); |
| 2370 } | 2370 } |
| 2371 | 2371 |
| 2372 VisitForStackValue(value); | 2372 VisitForStackValue(value); |
| 2373 if (NeedsHomeObject(value)) { | 2373 if (NeedsHomeObject(value)) { |
| 2374 EmitSetHomeObject(value, 2, property->GetSlot()); | 2374 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 2375 } | 2375 } |
| 2376 | 2376 |
| 2377 switch (property->kind()) { | 2377 switch (property->kind()) { |
| 2378 case ObjectLiteral::Property::CONSTANT: | 2378 case ObjectLiteral::Property::CONSTANT: |
| 2379 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2379 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 2380 case ObjectLiteral::Property::PROTOTYPE: | 2380 case ObjectLiteral::Property::PROTOTYPE: |
| 2381 UNREACHABLE(); | 2381 UNREACHABLE(); |
| 2382 case ObjectLiteral::Property::COMPUTED: | 2382 case ObjectLiteral::Property::COMPUTED: |
| 2383 __ CallRuntime(Runtime::kDefineClassMethod, 3); | 2383 __ CallRuntime(Runtime::kDefineClassMethod); |
| 2384 break; | 2384 break; |
| 2385 | 2385 |
| 2386 case ObjectLiteral::Property::GETTER: | 2386 case ObjectLiteral::Property::GETTER: |
| 2387 __ mov(r3, Operand(Smi::FromInt(DONT_ENUM))); | 2387 __ mov(r3, Operand(Smi::FromInt(DONT_ENUM))); |
| 2388 __ push(r3); | 2388 __ push(r3); |
| 2389 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 2389 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
| 2390 break; | 2390 break; |
| 2391 | 2391 |
| 2392 case ObjectLiteral::Property::SETTER: | 2392 case ObjectLiteral::Property::SETTER: |
| 2393 __ mov(r3, Operand(Smi::FromInt(DONT_ENUM))); | 2393 __ mov(r3, Operand(Smi::FromInt(DONT_ENUM))); |
| 2394 __ push(r3); | 2394 __ push(r3); |
| 2395 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 2395 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
| 2396 break; | 2396 break; |
| 2397 | 2397 |
| 2398 default: | 2398 default: |
| 2399 UNREACHABLE(); | 2399 UNREACHABLE(); |
| 2400 } | 2400 } |
| 2401 } | 2401 } |
| 2402 | 2402 |
| 2403 // Set both the prototype and constructor to have fast properties, and also | 2403 // Set both the prototype and constructor to have fast properties, and also |
| 2404 // freeze them in strong mode. | 2404 // freeze them in strong mode. |
| 2405 __ CallRuntime(Runtime::kFinalizeClassDefinition, 2); | 2405 __ CallRuntime(Runtime::kFinalizeClassDefinition); |
| 2406 } | 2406 } |
| 2407 | 2407 |
| 2408 | 2408 |
| 2409 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { | 2409 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
| 2410 __ pop(r4); | 2410 __ pop(r4); |
| 2411 Handle<Code> code = | 2411 Handle<Code> code = |
| 2412 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); | 2412 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); |
| 2413 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2413 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2414 CallIC(code, expr->BinaryOperationFeedbackId()); | 2414 CallIC(code, expr->BinaryOperationFeedbackId()); |
| 2415 patch_site.EmitPatchInfo(); | 2415 patch_site.EmitPatchInfo(); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2523 // Non-initializing assignment to let variable needs a write barrier. | 2523 // Non-initializing assignment to let variable needs a write barrier. |
| 2524 DCHECK(!var->IsLookupSlot()); | 2524 DCHECK(!var->IsLookupSlot()); |
| 2525 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2525 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2526 Label assign; | 2526 Label assign; |
| 2527 MemOperand location = VarOperand(var, r4); | 2527 MemOperand location = VarOperand(var, r4); |
| 2528 __ LoadP(r6, location); | 2528 __ LoadP(r6, location); |
| 2529 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); | 2529 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); |
| 2530 __ bne(&assign); | 2530 __ bne(&assign); |
| 2531 __ mov(r6, Operand(var->name())); | 2531 __ mov(r6, Operand(var->name())); |
| 2532 __ push(r6); | 2532 __ push(r6); |
| 2533 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2533 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2534 // Perform the assignment. | 2534 // Perform the assignment. |
| 2535 __ bind(&assign); | 2535 __ bind(&assign); |
| 2536 EmitStoreToStackLocalOrContextSlot(var, location); | 2536 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2537 | 2537 |
| 2538 } else if (var->mode() == CONST && op != Token::INIT) { | 2538 } else if (var->mode() == CONST && op != Token::INIT) { |
| 2539 // Assignment to const variable needs a write barrier. | 2539 // Assignment to const variable needs a write barrier. |
| 2540 DCHECK(!var->IsLookupSlot()); | 2540 DCHECK(!var->IsLookupSlot()); |
| 2541 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2541 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2542 Label const_error; | 2542 Label const_error; |
| 2543 MemOperand location = VarOperand(var, r4); | 2543 MemOperand location = VarOperand(var, r4); |
| 2544 __ LoadP(r6, location); | 2544 __ LoadP(r6, location); |
| 2545 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); | 2545 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); |
| 2546 __ bne(&const_error); | 2546 __ bne(&const_error); |
| 2547 __ mov(r6, Operand(var->name())); | 2547 __ mov(r6, Operand(var->name())); |
| 2548 __ push(r6); | 2548 __ push(r6); |
| 2549 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2549 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2550 __ bind(&const_error); | 2550 __ bind(&const_error); |
| 2551 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2551 __ CallRuntime(Runtime::kThrowConstAssignError); |
| 2552 | 2552 |
| 2553 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | 2553 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
| 2554 // Initializing assignment to const {this} needs a write barrier. | 2554 // Initializing assignment to const {this} needs a write barrier. |
| 2555 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2555 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2556 Label uninitialized_this; | 2556 Label uninitialized_this; |
| 2557 MemOperand location = VarOperand(var, r4); | 2557 MemOperand location = VarOperand(var, r4); |
| 2558 __ LoadP(r6, location); | 2558 __ LoadP(r6, location); |
| 2559 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); | 2559 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); |
| 2560 __ beq(&uninitialized_this); | 2560 __ beq(&uninitialized_this); |
| 2561 __ mov(r4, Operand(var->name())); | 2561 __ mov(r4, Operand(var->name())); |
| 2562 __ push(r4); | 2562 __ push(r4); |
| 2563 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2563 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2564 __ bind(&uninitialized_this); | 2564 __ bind(&uninitialized_this); |
| 2565 EmitStoreToStackLocalOrContextSlot(var, location); | 2565 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2566 | 2566 |
| 2567 } else if (!var->is_const_mode() || | 2567 } else if (!var->is_const_mode() || |
| 2568 (var->mode() == CONST && op == Token::INIT)) { | 2568 (var->mode() == CONST && op == Token::INIT)) { |
| 2569 if (var->IsLookupSlot()) { | 2569 if (var->IsLookupSlot()) { |
| 2570 // Assignment to var. | 2570 // Assignment to var. |
| 2571 __ push(r3); // Value. | 2571 __ push(r3); // Value. |
| 2572 __ mov(r4, Operand(var->name())); | 2572 __ mov(r4, Operand(var->name())); |
| 2573 __ mov(r3, Operand(Smi::FromInt(language_mode()))); | 2573 __ mov(r3, Operand(Smi::FromInt(language_mode()))); |
| 2574 __ Push(cp, r4, r3); // Context, name, language mode. | 2574 __ Push(cp, r4, r3); // Context, name, language mode. |
| 2575 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2575 __ CallRuntime(Runtime::kStoreLookupSlot); |
| 2576 } else { | 2576 } else { |
| 2577 // Assignment to var or initializing assignment to let/const in harmony | 2577 // Assignment to var or initializing assignment to let/const in harmony |
| 2578 // mode. | 2578 // mode. |
| 2579 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 2579 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
| 2580 MemOperand location = VarOperand(var, r4); | 2580 MemOperand location = VarOperand(var, r4); |
| 2581 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { | 2581 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { |
| 2582 // Check for an uninitialized let binding. | 2582 // Check for an uninitialized let binding. |
| 2583 __ LoadP(r5, location); | 2583 __ LoadP(r5, location); |
| 2584 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | 2584 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
| 2585 __ Check(eq, kLetBindingReInitialization); | 2585 __ Check(eq, kLetBindingReInitialization); |
| 2586 } | 2586 } |
| 2587 EmitStoreToStackLocalOrContextSlot(var, location); | 2587 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2588 } | 2588 } |
| 2589 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { | 2589 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { |
| 2590 // Const initializers need a write barrier. | 2590 // Const initializers need a write barrier. |
| 2591 DCHECK(!var->IsParameter()); // No const parameters. | 2591 DCHECK(!var->IsParameter()); // No const parameters. |
| 2592 if (var->IsLookupSlot()) { | 2592 if (var->IsLookupSlot()) { |
| 2593 __ push(r3); | 2593 __ push(r3); |
| 2594 __ mov(r3, Operand(var->name())); | 2594 __ mov(r3, Operand(var->name())); |
| 2595 __ Push(cp, r3); // Context and name. | 2595 __ Push(cp, r3); // Context and name. |
| 2596 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2596 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot); |
| 2597 } else { | 2597 } else { |
| 2598 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2598 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2599 Label skip; | 2599 Label skip; |
| 2600 MemOperand location = VarOperand(var, r4); | 2600 MemOperand location = VarOperand(var, r4); |
| 2601 __ LoadP(r5, location); | 2601 __ LoadP(r5, location); |
| 2602 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | 2602 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
| 2603 __ bne(&skip); | 2603 __ bne(&skip); |
| 2604 EmitStoreToStackLocalOrContextSlot(var, location); | 2604 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2605 __ bind(&skip); | 2605 __ bind(&skip); |
| 2606 } | 2606 } |
| 2607 | 2607 |
| 2608 } else { | 2608 } else { |
| 2609 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); | 2609 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); |
| 2610 if (is_strict(language_mode())) { | 2610 if (is_strict(language_mode())) { |
| 2611 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2611 __ CallRuntime(Runtime::kThrowConstAssignError); |
| 2612 } | 2612 } |
| 2613 // Silently ignore store in sloppy mode. | 2613 // Silently ignore store in sloppy mode. |
| 2614 } | 2614 } |
| 2615 } | 2615 } |
| 2616 | 2616 |
| 2617 | 2617 |
| 2618 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2618 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2619 // Assignment to a property, using a named store IC. | 2619 // Assignment to a property, using a named store IC. |
| 2620 Property* prop = expr->target()->AsProperty(); | 2620 Property* prop = expr->target()->AsProperty(); |
| 2621 DCHECK(prop != NULL); | 2621 DCHECK(prop != NULL); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2636 // Assignment to named property of super. | 2636 // Assignment to named property of super. |
| 2637 // r3 : value | 2637 // r3 : value |
| 2638 // stack : receiver ('this'), home_object | 2638 // stack : receiver ('this'), home_object |
| 2639 DCHECK(prop != NULL); | 2639 DCHECK(prop != NULL); |
| 2640 Literal* key = prop->key()->AsLiteral(); | 2640 Literal* key = prop->key()->AsLiteral(); |
| 2641 DCHECK(key != NULL); | 2641 DCHECK(key != NULL); |
| 2642 | 2642 |
| 2643 __ Push(key->value()); | 2643 __ Push(key->value()); |
| 2644 __ Push(r3); | 2644 __ Push(r3); |
| 2645 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict | 2645 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
| 2646 : Runtime::kStoreToSuper_Sloppy), | 2646 : Runtime::kStoreToSuper_Sloppy)); |
| 2647 4); | |
| 2648 } | 2647 } |
| 2649 | 2648 |
| 2650 | 2649 |
| 2651 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { | 2650 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
| 2652 // Assignment to named property of super. | 2651 // Assignment to named property of super. |
| 2653 // r3 : value | 2652 // r3 : value |
| 2654 // stack : receiver ('this'), home_object, key | 2653 // stack : receiver ('this'), home_object, key |
| 2655 DCHECK(prop != NULL); | 2654 DCHECK(prop != NULL); |
| 2656 | 2655 |
| 2657 __ Push(r3); | 2656 __ Push(r3); |
| 2658 __ CallRuntime( | 2657 __ CallRuntime((is_strict(language_mode()) |
| 2659 (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 2658 ? Runtime::kStoreKeyedToSuper_Strict |
| 2660 : Runtime::kStoreKeyedToSuper_Sloppy), | 2659 : Runtime::kStoreKeyedToSuper_Sloppy)); |
| 2661 4); | |
| 2662 } | 2660 } |
| 2663 | 2661 |
| 2664 | 2662 |
| 2665 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2663 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2666 // Assignment to a property, using a keyed store IC. | 2664 // Assignment to a property, using a keyed store IC. |
| 2667 __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); | 2665 __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); |
| 2668 DCHECK(StoreDescriptor::ValueRegister().is(r3)); | 2666 DCHECK(StoreDescriptor::ValueRegister().is(r3)); |
| 2669 | 2667 |
| 2670 Handle<Code> ic = | 2668 Handle<Code> ic = |
| 2671 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); | 2669 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2774 __ Push(key->value()); | 2772 __ Push(key->value()); |
| 2775 __ Push(Smi::FromInt(language_mode())); | 2773 __ Push(Smi::FromInt(language_mode())); |
| 2776 | 2774 |
| 2777 // Stack here: | 2775 // Stack here: |
| 2778 // - home_object | 2776 // - home_object |
| 2779 // - this (receiver) | 2777 // - this (receiver) |
| 2780 // - this (receiver) <-- LoadFromSuper will pop here and below. | 2778 // - this (receiver) <-- LoadFromSuper will pop here and below. |
| 2781 // - home_object | 2779 // - home_object |
| 2782 // - key | 2780 // - key |
| 2783 // - language_mode | 2781 // - language_mode |
| 2784 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2782 __ CallRuntime(Runtime::kLoadFromSuper); |
| 2785 | 2783 |
| 2786 // Replace home_object with target function. | 2784 // Replace home_object with target function. |
| 2787 __ StoreP(r3, MemOperand(sp, kPointerSize)); | 2785 __ StoreP(r3, MemOperand(sp, kPointerSize)); |
| 2788 | 2786 |
| 2789 // Stack here: | 2787 // Stack here: |
| 2790 // - target function | 2788 // - target function |
| 2791 // - this (receiver) | 2789 // - this (receiver) |
| 2792 EmitCall(expr); | 2790 EmitCall(expr); |
| 2793 } | 2791 } |
| 2794 | 2792 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2833 VisitForStackValue(prop->key()); | 2831 VisitForStackValue(prop->key()); |
| 2834 __ Push(Smi::FromInt(language_mode())); | 2832 __ Push(Smi::FromInt(language_mode())); |
| 2835 | 2833 |
| 2836 // Stack here: | 2834 // Stack here: |
| 2837 // - home_object | 2835 // - home_object |
| 2838 // - this (receiver) | 2836 // - this (receiver) |
| 2839 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. | 2837 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. |
| 2840 // - home_object | 2838 // - home_object |
| 2841 // - key | 2839 // - key |
| 2842 // - language_mode | 2840 // - language_mode |
| 2843 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2841 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
| 2844 | 2842 |
| 2845 // Replace home_object with target function. | 2843 // Replace home_object with target function. |
| 2846 __ StoreP(r3, MemOperand(sp, kPointerSize)); | 2844 __ StoreP(r3, MemOperand(sp, kPointerSize)); |
| 2847 | 2845 |
| 2848 // Stack here: | 2846 // Stack here: |
| 2849 // - target function | 2847 // - target function |
| 2850 // - this (receiver) | 2848 // - this (receiver) |
| 2851 EmitCall(expr); | 2849 EmitCall(expr); |
| 2852 } | 2850 } |
| 2853 | 2851 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2888 __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 2886 __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 2889 | 2887 |
| 2890 // r5: language mode. | 2888 // r5: language mode. |
| 2891 __ LoadSmiLiteral(r5, Smi::FromInt(language_mode())); | 2889 __ LoadSmiLiteral(r5, Smi::FromInt(language_mode())); |
| 2892 | 2890 |
| 2893 // r4: the start position of the scope the calls resides in. | 2891 // r4: the start position of the scope the calls resides in. |
| 2894 __ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position())); | 2892 __ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position())); |
| 2895 | 2893 |
| 2896 // Do the runtime call. | 2894 // Do the runtime call. |
| 2897 __ Push(r7, r6, r5, r4); | 2895 __ Push(r7, r6, r5, r4); |
| 2898 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2896 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); |
| 2899 } | 2897 } |
| 2900 | 2898 |
| 2901 | 2899 |
| 2902 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | 2900 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. |
| 2903 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | 2901 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
| 2904 VariableProxy* callee = expr->expression()->AsVariableProxy(); | 2902 VariableProxy* callee = expr->expression()->AsVariableProxy(); |
| 2905 if (callee->var()->IsLookupSlot()) { | 2903 if (callee->var()->IsLookupSlot()) { |
| 2906 Label slow, done; | 2904 Label slow, done; |
| 2907 SetExpressionPosition(callee); | 2905 SetExpressionPosition(callee); |
| 2908 // Generate code for loading from variables potentially shadowed by | 2906 // Generate code for loading from variables potentially shadowed by |
| 2909 // eval-introduced variables. | 2907 // eval-introduced variables. |
| 2910 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | 2908 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |
| 2911 | 2909 |
| 2912 __ bind(&slow); | 2910 __ bind(&slow); |
| 2913 // Call the runtime to find the function to call (returned in r3) and | 2911 // Call the runtime to find the function to call (returned in r3) and |
| 2914 // the object holding it (returned in r4). | 2912 // the object holding it (returned in r4). |
| 2915 DCHECK(!context_register().is(r5)); | 2913 DCHECK(!context_register().is(r5)); |
| 2916 __ mov(r5, Operand(callee->name())); | 2914 __ mov(r5, Operand(callee->name())); |
| 2917 __ Push(context_register(), r5); | 2915 __ Push(context_register(), r5); |
| 2918 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 2916 __ CallRuntime(Runtime::kLoadLookupSlot); |
| 2919 __ Push(r3, r4); // Function, receiver. | 2917 __ Push(r3, r4); // Function, receiver. |
| 2920 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); | 2918 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
| 2921 | 2919 |
| 2922 // If fast case code has been generated, emit code to push the function | 2920 // If fast case code has been generated, emit code to push the function |
| 2923 // and receiver and have the slow path jump around this code. | 2921 // and receiver and have the slow path jump around this code. |
| 2924 if (done.is_linked()) { | 2922 if (done.is_linked()) { |
| 2925 Label call; | 2923 Label call; |
| 2926 __ b(&call); | 2924 __ b(&call); |
| 2927 __ bind(&done); | 2925 __ bind(&done); |
| 2928 // Push function. | 2926 // Push function. |
| (...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3565 ZoneList<Expression*>* args = expr->arguments(); | 3563 ZoneList<Expression*>* args = expr->arguments(); |
| 3566 DCHECK_EQ(1, args->length()); | 3564 DCHECK_EQ(1, args->length()); |
| 3567 | 3565 |
| 3568 // Load the argument into r3 and convert it. | 3566 // Load the argument into r3 and convert it. |
| 3569 VisitForAccumulatorValue(args->at(0)); | 3567 VisitForAccumulatorValue(args->at(0)); |
| 3570 | 3568 |
| 3571 // Convert the object to an integer. | 3569 // Convert the object to an integer. |
| 3572 Label done_convert; | 3570 Label done_convert; |
| 3573 __ JumpIfSmi(r3, &done_convert); | 3571 __ JumpIfSmi(r3, &done_convert); |
| 3574 __ Push(r3); | 3572 __ Push(r3); |
| 3575 __ CallRuntime(Runtime::kToInteger, 1); | 3573 __ CallRuntime(Runtime::kToInteger); |
| 3576 __ bind(&done_convert); | 3574 __ bind(&done_convert); |
| 3577 context()->Plug(r3); | 3575 context()->Plug(r3); |
| 3578 } | 3576 } |
| 3579 | 3577 |
| 3580 | 3578 |
| 3581 void FullCodeGenerator::EmitToName(CallRuntime* expr) { | 3579 void FullCodeGenerator::EmitToName(CallRuntime* expr) { |
| 3582 ZoneList<Expression*>* args = expr->arguments(); | 3580 ZoneList<Expression*>* args = expr->arguments(); |
| 3583 DCHECK_EQ(1, args->length()); | 3581 DCHECK_EQ(1, args->length()); |
| 3584 | 3582 |
| 3585 // Load the argument into r3 and convert it. | 3583 // Load the argument into r3 and convert it. |
| 3586 VisitForAccumulatorValue(args->at(0)); | 3584 VisitForAccumulatorValue(args->at(0)); |
| 3587 | 3585 |
| 3588 Label convert, done_convert; | 3586 Label convert, done_convert; |
| 3589 __ JumpIfSmi(r3, &convert); | 3587 __ JumpIfSmi(r3, &convert); |
| 3590 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); | 3588 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); |
| 3591 __ CompareObjectType(r3, r4, r4, LAST_NAME_TYPE); | 3589 __ CompareObjectType(r3, r4, r4, LAST_NAME_TYPE); |
| 3592 __ ble(&done_convert); | 3590 __ ble(&done_convert); |
| 3593 __ bind(&convert); | 3591 __ bind(&convert); |
| 3594 __ Push(r3); | 3592 __ Push(r3); |
| 3595 __ CallRuntime(Runtime::kToName, 1); | 3593 __ CallRuntime(Runtime::kToName); |
| 3596 __ bind(&done_convert); | 3594 __ bind(&done_convert); |
| 3597 context()->Plug(r3); | 3595 context()->Plug(r3); |
| 3598 } | 3596 } |
| 3599 | 3597 |
| 3600 | 3598 |
| 3601 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3599 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
| 3602 ZoneList<Expression*>* args = expr->arguments(); | 3600 ZoneList<Expression*>* args = expr->arguments(); |
| 3603 DCHECK(args->length() == 1); | 3601 DCHECK(args->length() == 1); |
| 3604 VisitForAccumulatorValue(args->at(0)); | 3602 VisitForAccumulatorValue(args->at(0)); |
| 3605 | 3603 |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4047 __ LoadRoot(r7, Heap::kEmptyFixedArrayRootIndex); | 4045 __ LoadRoot(r7, Heap::kEmptyFixedArrayRootIndex); |
| 4048 __ StoreP(r4, FieldMemOperand(r3, HeapObject::kMapOffset), r0); | 4046 __ StoreP(r4, FieldMemOperand(r3, HeapObject::kMapOffset), r0); |
| 4049 __ StoreP(r7, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0); | 4047 __ StoreP(r7, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0); |
| 4050 __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0); | 4048 __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0); |
| 4051 __ StoreP(r5, FieldMemOperand(r3, JSIteratorResult::kValueOffset), r0); | 4049 __ StoreP(r5, FieldMemOperand(r3, JSIteratorResult::kValueOffset), r0); |
| 4052 __ StoreP(r6, FieldMemOperand(r3, JSIteratorResult::kDoneOffset), r0); | 4050 __ StoreP(r6, FieldMemOperand(r3, JSIteratorResult::kDoneOffset), r0); |
| 4053 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 4051 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
| 4054 __ b(&done); | 4052 __ b(&done); |
| 4055 | 4053 |
| 4056 __ bind(&runtime); | 4054 __ bind(&runtime); |
| 4057 __ CallRuntime(Runtime::kCreateIterResultObject, 2); | 4055 __ CallRuntime(Runtime::kCreateIterResultObject); |
| 4058 | 4056 |
| 4059 __ bind(&done); | 4057 __ bind(&done); |
| 4060 context()->Plug(r3); | 4058 context()->Plug(r3); |
| 4061 } | 4059 } |
| 4062 | 4060 |
| 4063 | 4061 |
| 4064 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 4062 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
| 4065 // Push undefined as the receiver. | 4063 // Push undefined as the receiver. |
| 4066 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); | 4064 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); |
| 4067 __ push(r3); | 4065 __ push(r3); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4140 case Token::DELETE: { | 4138 case Token::DELETE: { |
| 4141 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4139 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 4142 Property* property = expr->expression()->AsProperty(); | 4140 Property* property = expr->expression()->AsProperty(); |
| 4143 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4141 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 4144 | 4142 |
| 4145 if (property != NULL) { | 4143 if (property != NULL) { |
| 4146 VisitForStackValue(property->obj()); | 4144 VisitForStackValue(property->obj()); |
| 4147 VisitForStackValue(property->key()); | 4145 VisitForStackValue(property->key()); |
| 4148 __ CallRuntime(is_strict(language_mode()) | 4146 __ CallRuntime(is_strict(language_mode()) |
| 4149 ? Runtime::kDeleteProperty_Strict | 4147 ? Runtime::kDeleteProperty_Strict |
| 4150 : Runtime::kDeleteProperty_Sloppy, | 4148 : Runtime::kDeleteProperty_Sloppy); |
| 4151 2); | |
| 4152 context()->Plug(r3); | 4149 context()->Plug(r3); |
| 4153 } else if (proxy != NULL) { | 4150 } else if (proxy != NULL) { |
| 4154 Variable* var = proxy->var(); | 4151 Variable* var = proxy->var(); |
| 4155 // Delete of an unqualified identifier is disallowed in strict mode but | 4152 // Delete of an unqualified identifier is disallowed in strict mode but |
| 4156 // "delete this" is allowed. | 4153 // "delete this" is allowed. |
| 4157 bool is_this = var->HasThisName(isolate()); | 4154 bool is_this = var->HasThisName(isolate()); |
| 4158 DCHECK(is_sloppy(language_mode()) || is_this); | 4155 DCHECK(is_sloppy(language_mode()) || is_this); |
| 4159 if (var->IsUnallocatedOrGlobalSlot()) { | 4156 if (var->IsUnallocatedOrGlobalSlot()) { |
| 4160 __ LoadGlobalObject(r5); | 4157 __ LoadGlobalObject(r5); |
| 4161 __ mov(r4, Operand(var->name())); | 4158 __ mov(r4, Operand(var->name())); |
| 4162 __ Push(r5, r4); | 4159 __ Push(r5, r4); |
| 4163 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); | 4160 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
| 4164 context()->Plug(r3); | 4161 context()->Plug(r3); |
| 4165 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4162 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4166 // Result of deleting non-global, non-dynamic variables is false. | 4163 // Result of deleting non-global, non-dynamic variables is false. |
| 4167 // The subexpression does not have side effects. | 4164 // The subexpression does not have side effects. |
| 4168 context()->Plug(is_this); | 4165 context()->Plug(is_this); |
| 4169 } else { | 4166 } else { |
| 4170 // Non-global variable. Call the runtime to try to delete from the | 4167 // Non-global variable. Call the runtime to try to delete from the |
| 4171 // context where the variable was introduced. | 4168 // context where the variable was introduced. |
| 4172 DCHECK(!context_register().is(r5)); | 4169 DCHECK(!context_register().is(r5)); |
| 4173 __ mov(r5, Operand(var->name())); | 4170 __ mov(r5, Operand(var->name())); |
| 4174 __ Push(context_register(), r5); | 4171 __ Push(context_register(), r5); |
| 4175 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); | 4172 __ CallRuntime(Runtime::kDeleteLookupSlot); |
| 4176 context()->Plug(r3); | 4173 context()->Plug(r3); |
| 4177 } | 4174 } |
| 4178 } else { | 4175 } else { |
| 4179 // Result of deleting non-property, non-variable reference is true. | 4176 // Result of deleting non-property, non-variable reference is true. |
| 4180 // The subexpression may have side effects. | 4177 // The subexpression may have side effects. |
| 4181 VisitForEffect(expr->expression()); | 4178 VisitForEffect(expr->expression()); |
| 4182 context()->Plug(true); | 4179 context()->Plug(true); |
| 4183 } | 4180 } |
| 4184 break; | 4181 break; |
| 4185 } | 4182 } |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4595 Label* if_false = NULL; | 4592 Label* if_false = NULL; |
| 4596 Label* fall_through = NULL; | 4593 Label* fall_through = NULL; |
| 4597 context()->PrepareTest(&materialize_true, &materialize_false, &if_true, | 4594 context()->PrepareTest(&materialize_true, &materialize_false, &if_true, |
| 4598 &if_false, &fall_through); | 4595 &if_false, &fall_through); |
| 4599 | 4596 |
| 4600 Token::Value op = expr->op(); | 4597 Token::Value op = expr->op(); |
| 4601 VisitForStackValue(expr->left()); | 4598 VisitForStackValue(expr->left()); |
| 4602 switch (op) { | 4599 switch (op) { |
| 4603 case Token::IN: | 4600 case Token::IN: |
| 4604 VisitForStackValue(expr->right()); | 4601 VisitForStackValue(expr->right()); |
| 4605 __ CallRuntime(Runtime::kHasProperty, 2); | 4602 __ CallRuntime(Runtime::kHasProperty); |
| 4606 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 4603 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
| 4607 __ CompareRoot(r3, Heap::kTrueValueRootIndex); | 4604 __ CompareRoot(r3, Heap::kTrueValueRootIndex); |
| 4608 Split(eq, if_true, if_false, fall_through); | 4605 Split(eq, if_true, if_false, fall_through); |
| 4609 break; | 4606 break; |
| 4610 | 4607 |
| 4611 case Token::INSTANCEOF: { | 4608 case Token::INSTANCEOF: { |
| 4612 VisitForAccumulatorValue(expr->right()); | 4609 VisitForAccumulatorValue(expr->right()); |
| 4613 __ pop(r4); | 4610 __ pop(r4); |
| 4614 InstanceOfStub stub(isolate()); | 4611 InstanceOfStub stub(isolate()); |
| 4615 __ CallStub(&stub); | 4612 __ CallStub(&stub); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4858 return ON_STACK_REPLACEMENT; | 4855 return ON_STACK_REPLACEMENT; |
| 4859 } | 4856 } |
| 4860 | 4857 |
| 4861 DCHECK(interrupt_address == | 4858 DCHECK(interrupt_address == |
| 4862 isolate->builtins()->OsrAfterStackCheck()->entry()); | 4859 isolate->builtins()->OsrAfterStackCheck()->entry()); |
| 4863 return OSR_AFTER_STACK_CHECK; | 4860 return OSR_AFTER_STACK_CHECK; |
| 4864 } | 4861 } |
| 4865 } // namespace internal | 4862 } // namespace internal |
| 4866 } // namespace v8 | 4863 } // namespace v8 |
| 4867 #endif // V8_TARGET_ARCH_PPC | 4864 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |