| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_MIPS64 | 5 #if V8_TARGET_ARCH_MIPS64 |
| 6 | 6 |
| 7 // Note on Mips implementation: | 7 // Note on Mips implementation: |
| 8 // | 8 // |
| 9 // The result_register() for mips is the 'v0' register, which is defined | 9 // The result_register() for mips is the 'v0' register, which is defined |
| 10 // by the ABI to contain function return values. However, the first | 10 // by the ABI to contain function return values. However, the first |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 { Comment cmnt(masm_, "[ Allocate locals"); | 144 { Comment cmnt(masm_, "[ Allocate locals"); |
| 145 int locals_count = info->scope()->num_stack_slots(); | 145 int locals_count = info->scope()->num_stack_slots(); |
| 146 // Generators allocate locals, if any, in context slots. | 146 // Generators allocate locals, if any, in context slots. |
| 147 DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); | 147 DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); |
| 148 if (locals_count > 0) { | 148 if (locals_count > 0) { |
| 149 if (locals_count >= 128) { | 149 if (locals_count >= 128) { |
| 150 Label ok; | 150 Label ok; |
| 151 __ Dsubu(t1, sp, Operand(locals_count * kPointerSize)); | 151 __ Dsubu(t1, sp, Operand(locals_count * kPointerSize)); |
| 152 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); | 152 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); |
| 153 __ Branch(&ok, hs, t1, Operand(a2)); | 153 __ Branch(&ok, hs, t1, Operand(a2)); |
| 154 __ CallRuntime(Runtime::kThrowStackOverflow, 0); | 154 __ CallRuntime(Runtime::kThrowStackOverflow); |
| 155 __ bind(&ok); | 155 __ bind(&ok); |
| 156 } | 156 } |
| 157 __ LoadRoot(t1, Heap::kUndefinedValueRootIndex); | 157 __ LoadRoot(t1, Heap::kUndefinedValueRootIndex); |
| 158 int kMaxPushes = FLAG_optimize_for_size ? 4 : 32; | 158 int kMaxPushes = FLAG_optimize_for_size ? 4 : 32; |
| 159 if (locals_count >= kMaxPushes) { | 159 if (locals_count >= kMaxPushes) { |
| 160 int loop_iterations = locals_count / kMaxPushes; | 160 int loop_iterations = locals_count / kMaxPushes; |
| 161 __ li(a2, Operand(loop_iterations)); | 161 __ li(a2, Operand(loop_iterations)); |
| 162 Label loop_header; | 162 Label loop_header; |
| 163 __ bind(&loop_header); | 163 __ bind(&loop_header); |
| 164 // Do pushes. | 164 // Do pushes. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 183 | 183 |
| 184 // Possibly allocate a local context. | 184 // Possibly allocate a local context. |
| 185 if (info->scope()->num_heap_slots() > 0) { | 185 if (info->scope()->num_heap_slots() > 0) { |
| 186 Comment cmnt(masm_, "[ Allocate context"); | 186 Comment cmnt(masm_, "[ Allocate context"); |
| 187 // Argument to NewContext is the function, which is still in a1. | 187 // Argument to NewContext is the function, which is still in a1. |
| 188 bool need_write_barrier = true; | 188 bool need_write_barrier = true; |
| 189 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 189 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 190 if (info->scope()->is_script_scope()) { | 190 if (info->scope()->is_script_scope()) { |
| 191 __ push(a1); | 191 __ push(a1); |
| 192 __ Push(info->scope()->GetScopeInfo(info->isolate())); | 192 __ Push(info->scope()->GetScopeInfo(info->isolate())); |
| 193 __ CallRuntime(Runtime::kNewScriptContext, 2); | 193 __ CallRuntime(Runtime::kNewScriptContext); |
| 194 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); | 194 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); |
| 195 // The new target value is not used, clobbering is safe. | 195 // The new target value is not used, clobbering is safe. |
| 196 DCHECK_NULL(info->scope()->new_target_var()); | 196 DCHECK_NULL(info->scope()->new_target_var()); |
| 197 } else { | 197 } else { |
| 198 if (info->scope()->new_target_var() != nullptr) { | 198 if (info->scope()->new_target_var() != nullptr) { |
| 199 __ push(a3); // Preserve new target. | 199 __ push(a3); // Preserve new target. |
| 200 } | 200 } |
| 201 if (slots <= FastNewContextStub::kMaximumSlots) { | 201 if (slots <= FastNewContextStub::kMaximumSlots) { |
| 202 FastNewContextStub stub(isolate(), slots); | 202 FastNewContextStub stub(isolate(), slots); |
| 203 __ CallStub(&stub); | 203 __ CallStub(&stub); |
| 204 // Result of FastNewContextStub is always in new space. | 204 // Result of FastNewContextStub is always in new space. |
| 205 need_write_barrier = false; | 205 need_write_barrier = false; |
| 206 } else { | 206 } else { |
| 207 __ push(a1); | 207 __ push(a1); |
| 208 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 208 __ CallRuntime(Runtime::kNewFunctionContext); |
| 209 } | 209 } |
| 210 if (info->scope()->new_target_var() != nullptr) { | 210 if (info->scope()->new_target_var() != nullptr) { |
| 211 __ pop(a3); // Restore new target. | 211 __ pop(a3); // Restore new target. |
| 212 } | 212 } |
| 213 } | 213 } |
| 214 function_in_register_a1 = false; | 214 function_in_register_a1 = false; |
| 215 // Context is returned in v0. It replaces the context passed to us. | 215 // Context is returned in v0. It replaces the context passed to us. |
| 216 // It's saved in the stack and kept live in cp. | 216 // It's saved in the stack and kept live in cp. |
| 217 __ mov(cp, v0); | 217 __ mov(cp, v0); |
| 218 __ sd(v0, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 218 __ sd(v0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); | 313 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); |
| 314 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( | 314 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( |
| 315 is_unmapped, literal()->has_duplicate_parameters()); | 315 is_unmapped, literal()->has_duplicate_parameters()); |
| 316 ArgumentsAccessStub stub(isolate(), type); | 316 ArgumentsAccessStub stub(isolate(), type); |
| 317 __ CallStub(&stub); | 317 __ CallStub(&stub); |
| 318 | 318 |
| 319 SetVar(arguments, v0, a1, a2); | 319 SetVar(arguments, v0, a1, a2); |
| 320 } | 320 } |
| 321 | 321 |
| 322 if (FLAG_trace) { | 322 if (FLAG_trace) { |
| 323 __ CallRuntime(Runtime::kTraceEnter, 0); | 323 __ CallRuntime(Runtime::kTraceEnter); |
| 324 } | 324 } |
| 325 | 325 |
| 326 // Visit the declarations and body unless there is an illegal | 326 // Visit the declarations and body unless there is an illegal |
| 327 // redeclaration. | 327 // redeclaration. |
| 328 if (scope()->HasIllegalRedeclaration()) { | 328 if (scope()->HasIllegalRedeclaration()) { |
| 329 Comment cmnt(masm_, "[ Declarations"); | 329 Comment cmnt(masm_, "[ Declarations"); |
| 330 VisitForEffect(scope()->GetIllegalRedeclaration()); | 330 VisitForEffect(scope()->GetIllegalRedeclaration()); |
| 331 | 331 |
| 332 } else { | 332 } else { |
| 333 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 333 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 void FullCodeGenerator::EmitReturnSequence() { | 433 void FullCodeGenerator::EmitReturnSequence() { |
| 434 Comment cmnt(masm_, "[ Return sequence"); | 434 Comment cmnt(masm_, "[ Return sequence"); |
| 435 if (return_label_.is_bound()) { | 435 if (return_label_.is_bound()) { |
| 436 __ Branch(&return_label_); | 436 __ Branch(&return_label_); |
| 437 } else { | 437 } else { |
| 438 __ bind(&return_label_); | 438 __ bind(&return_label_); |
| 439 if (FLAG_trace) { | 439 if (FLAG_trace) { |
| 440 // Push the return value on the stack as the parameter. | 440 // Push the return value on the stack as the parameter. |
| 441 // Runtime::TraceExit returns its parameter in v0. | 441 // Runtime::TraceExit returns its parameter in v0. |
| 442 __ push(v0); | 442 __ push(v0); |
| 443 __ CallRuntime(Runtime::kTraceExit, 1); | 443 __ CallRuntime(Runtime::kTraceExit); |
| 444 } | 444 } |
| 445 // Pretend that the exit is a backwards jump to the entry. | 445 // Pretend that the exit is a backwards jump to the entry. |
| 446 int weight = 1; | 446 int weight = 1; |
| 447 if (info_->ShouldSelfOptimize()) { | 447 if (info_->ShouldSelfOptimize()) { |
| 448 weight = FLAG_interrupt_budget / FLAG_self_opt_count; | 448 weight = FLAG_interrupt_budget / FLAG_self_opt_count; |
| 449 } else { | 449 } else { |
| 450 int distance = masm_->pc_offset(); | 450 int distance = masm_->pc_offset(); |
| 451 weight = Min(kMaxBackEdgeWeight, | 451 weight = Min(kMaxBackEdgeWeight, |
| 452 Max(1, distance / kCodeSizeMultiplier)); | 452 Max(1, distance / kCodeSizeMultiplier)); |
| 453 } | 453 } |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 // 'undefined') because we may have a (legal) redeclaration and we | 843 // 'undefined') because we may have a (legal) redeclaration and we |
| 844 // must not destroy the current value. | 844 // must not destroy the current value. |
| 845 if (hole_init) { | 845 if (hole_init) { |
| 846 __ LoadRoot(a0, Heap::kTheHoleValueRootIndex); | 846 __ LoadRoot(a0, Heap::kTheHoleValueRootIndex); |
| 847 } else { | 847 } else { |
| 848 DCHECK(Smi::FromInt(0) == 0); | 848 DCHECK(Smi::FromInt(0) == 0); |
| 849 __ mov(a0, zero_reg); // Smi::FromInt(0) indicates no initial value. | 849 __ mov(a0, zero_reg); // Smi::FromInt(0) indicates no initial value. |
| 850 } | 850 } |
| 851 __ Push(a2, a0); | 851 __ Push(a2, a0); |
| 852 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); | 852 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
| 853 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 853 __ CallRuntime(Runtime::kDeclareLookupSlot); |
| 854 break; | 854 break; |
| 855 } | 855 } |
| 856 } | 856 } |
| 857 } | 857 } |
| 858 | 858 |
| 859 | 859 |
| 860 void FullCodeGenerator::VisitFunctionDeclaration( | 860 void FullCodeGenerator::VisitFunctionDeclaration( |
| 861 FunctionDeclaration* declaration) { | 861 FunctionDeclaration* declaration) { |
| 862 VariableProxy* proxy = declaration->proxy(); | 862 VariableProxy* proxy = declaration->proxy(); |
| 863 Variable* variable = proxy->var(); | 863 Variable* variable = proxy->var(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 break; | 900 break; |
| 901 } | 901 } |
| 902 | 902 |
| 903 case VariableLocation::LOOKUP: { | 903 case VariableLocation::LOOKUP: { |
| 904 Comment cmnt(masm_, "[ FunctionDeclaration"); | 904 Comment cmnt(masm_, "[ FunctionDeclaration"); |
| 905 __ li(a2, Operand(variable->name())); | 905 __ li(a2, Operand(variable->name())); |
| 906 __ Push(a2); | 906 __ Push(a2); |
| 907 // Push initial value for function declaration. | 907 // Push initial value for function declaration. |
| 908 VisitForStackValue(declaration->fun()); | 908 VisitForStackValue(declaration->fun()); |
| 909 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); | 909 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
| 910 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 910 __ CallRuntime(Runtime::kDeclareLookupSlot); |
| 911 break; | 911 break; |
| 912 } | 912 } |
| 913 } | 913 } |
| 914 } | 914 } |
| 915 | 915 |
| 916 | 916 |
| 917 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 917 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 918 // Call the runtime to declare the globals. | 918 // Call the runtime to declare the globals. |
| 919 __ li(a1, Operand(pairs)); | 919 __ li(a1, Operand(pairs)); |
| 920 __ li(a0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); | 920 __ li(a0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); |
| 921 __ Push(a1, a0); | 921 __ Push(a1, a0); |
| 922 __ CallRuntime(Runtime::kDeclareGlobals, 2); | 922 __ CallRuntime(Runtime::kDeclareGlobals); |
| 923 // Return value is ignored. | 923 // Return value is ignored. |
| 924 } | 924 } |
| 925 | 925 |
| 926 | 926 |
| 927 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 927 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
| 928 // Call the runtime to declare the modules. | 928 // Call the runtime to declare the modules. |
| 929 __ Push(descriptions); | 929 __ Push(descriptions); |
| 930 __ CallRuntime(Runtime::kDeclareModules, 1); | 930 __ CallRuntime(Runtime::kDeclareModules); |
| 931 // Return value is ignored. | 931 // Return value is ignored. |
| 932 } | 932 } |
| 933 | 933 |
| 934 | 934 |
| 935 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 935 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 936 Comment cmnt(masm_, "[ SwitchStatement"); | 936 Comment cmnt(masm_, "[ SwitchStatement"); |
| 937 Breakable nested_statement(this, stmt); | 937 Breakable nested_statement(this, stmt); |
| 938 SetStatementPosition(stmt); | 938 SetStatementPosition(stmt); |
| 939 | 939 |
| 940 // Keep the switch value on the stack until a case matches. | 940 // Keep the switch value on the stack until a case matches. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1073 | 1073 |
| 1074 // The enum cache is valid. Load the map of the object being | 1074 // The enum cache is valid. Load the map of the object being |
| 1075 // iterated over and use the cache for the iteration. | 1075 // iterated over and use the cache for the iteration. |
| 1076 Label use_cache; | 1076 Label use_cache; |
| 1077 __ ld(v0, FieldMemOperand(a0, HeapObject::kMapOffset)); | 1077 __ ld(v0, FieldMemOperand(a0, HeapObject::kMapOffset)); |
| 1078 __ Branch(&use_cache); | 1078 __ Branch(&use_cache); |
| 1079 | 1079 |
| 1080 // Get the set of properties to enumerate. | 1080 // Get the set of properties to enumerate. |
| 1081 __ bind(&call_runtime); | 1081 __ bind(&call_runtime); |
| 1082 __ push(a0); // Duplicate the enumerable object on the stack. | 1082 __ push(a0); // Duplicate the enumerable object on the stack. |
| 1083 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 1083 __ CallRuntime(Runtime::kGetPropertyNamesFast); |
| 1084 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); | 1084 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); |
| 1085 | 1085 |
| 1086 // If we got a map from the runtime call, we can do a fast | 1086 // If we got a map from the runtime call, we can do a fast |
| 1087 // modification check. Otherwise, we got a fixed array, and we have | 1087 // modification check. Otherwise, we got a fixed array, and we have |
| 1088 // to do a slow check. | 1088 // to do a slow check. |
| 1089 Label fixed_array; | 1089 Label fixed_array; |
| 1090 __ ld(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); | 1090 __ ld(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); |
| 1091 __ LoadRoot(at, Heap::kMetaMapRootIndex); | 1091 __ LoadRoot(at, Heap::kMetaMapRootIndex); |
| 1092 __ Branch(&fixed_array, ne, a2, Operand(at)); | 1092 __ Branch(&fixed_array, ne, a2, Operand(at)); |
| 1093 | 1093 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1150 // If not, we may have to filter the key. | 1150 // If not, we may have to filter the key. |
| 1151 Label update_each; | 1151 Label update_each; |
| 1152 __ ld(a1, MemOperand(sp, 4 * kPointerSize)); | 1152 __ ld(a1, MemOperand(sp, 4 * kPointerSize)); |
| 1153 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset)); | 1153 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset)); |
| 1154 __ Branch(&update_each, eq, a4, Operand(a2)); | 1154 __ Branch(&update_each, eq, a4, Operand(a2)); |
| 1155 | 1155 |
| 1156 // Convert the entry to a string or (smi) 0 if it isn't a property | 1156 // Convert the entry to a string or (smi) 0 if it isn't a property |
| 1157 // any more. If the property has been removed while iterating, we | 1157 // any more. If the property has been removed while iterating, we |
| 1158 // just skip it. | 1158 // just skip it. |
| 1159 __ Push(a1, a3); // Enumerable and current entry. | 1159 __ Push(a1, a3); // Enumerable and current entry. |
| 1160 __ CallRuntime(Runtime::kForInFilter, 2); | 1160 __ CallRuntime(Runtime::kForInFilter); |
| 1161 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); | 1161 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); |
| 1162 __ mov(a3, result_register()); | 1162 __ mov(a3, result_register()); |
| 1163 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 1163 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 1164 __ Branch(loop_statement.continue_label(), eq, a3, Operand(at)); | 1164 __ Branch(loop_statement.continue_label(), eq, a3, Operand(at)); |
| 1165 | 1165 |
| 1166 // Update the 'each' property or variable from the possibly filtered | 1166 // Update the 'each' property or variable from the possibly filtered |
| 1167 // entry in register a3. | 1167 // entry in register a3. |
| 1168 __ bind(&update_each); | 1168 __ bind(&update_each); |
| 1169 __ mov(result_register(), a3); | 1169 __ mov(result_register(), a3); |
| 1170 // Perform the assignment as if via '='. | 1170 // Perform the assignment as if via '='. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1210 if (!FLAG_always_opt && | 1210 if (!FLAG_always_opt && |
| 1211 !FLAG_prepare_always_opt && | 1211 !FLAG_prepare_always_opt && |
| 1212 !pretenure && | 1212 !pretenure && |
| 1213 scope()->is_function_scope() && | 1213 scope()->is_function_scope() && |
| 1214 info->num_literals() == 0) { | 1214 info->num_literals() == 0) { |
| 1215 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); | 1215 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); |
| 1216 __ li(a2, Operand(info)); | 1216 __ li(a2, Operand(info)); |
| 1217 __ CallStub(&stub); | 1217 __ CallStub(&stub); |
| 1218 } else { | 1218 } else { |
| 1219 __ Push(info); | 1219 __ Push(info); |
| 1220 __ CallRuntime( | 1220 __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured |
| 1221 pretenure ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure, 1); | 1221 : Runtime::kNewClosure); |
| 1222 } | 1222 } |
| 1223 context()->Plug(v0); | 1223 context()->Plug(v0); |
| 1224 } | 1224 } |
| 1225 | 1225 |
| 1226 | 1226 |
| 1227 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, | 1227 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, |
| 1228 FeedbackVectorSlot slot) { | 1228 FeedbackVectorSlot slot) { |
| 1229 DCHECK(NeedsHomeObject(initializer)); | 1229 DCHECK(NeedsHomeObject(initializer)); |
| 1230 __ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); | 1230 __ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); |
| 1231 __ li(StoreDescriptor::NameRegister(), | 1231 __ li(StoreDescriptor::NameRegister(), |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1351 local->mode() == CONST_LEGACY) { | 1351 local->mode() == CONST_LEGACY) { |
| 1352 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1352 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 1353 __ dsubu(at, v0, at); // Sub as compare: at == 0 on eq. | 1353 __ dsubu(at, v0, at); // Sub as compare: at == 0 on eq. |
| 1354 if (local->mode() == CONST_LEGACY) { | 1354 if (local->mode() == CONST_LEGACY) { |
| 1355 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 1355 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
| 1356 __ Movz(v0, a0, at); // Conditional move: return Undefined if TheHole. | 1356 __ Movz(v0, a0, at); // Conditional move: return Undefined if TheHole. |
| 1357 } else { // LET || CONST | 1357 } else { // LET || CONST |
| 1358 __ Branch(done, ne, at, Operand(zero_reg)); | 1358 __ Branch(done, ne, at, Operand(zero_reg)); |
| 1359 __ li(a0, Operand(var->name())); | 1359 __ li(a0, Operand(var->name())); |
| 1360 __ push(a0); | 1360 __ push(a0); |
| 1361 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1361 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1362 } | 1362 } |
| 1363 } | 1363 } |
| 1364 __ Branch(done); | 1364 __ Branch(done); |
| 1365 } | 1365 } |
| 1366 } | 1366 } |
| 1367 | 1367 |
| 1368 | 1368 |
| 1369 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1369 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1370 TypeofMode typeof_mode) { | 1370 TypeofMode typeof_mode) { |
| 1371 Variable* var = proxy->var(); | 1371 Variable* var = proxy->var(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1408 GetVar(v0, var); | 1408 GetVar(v0, var); |
| 1409 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1409 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 1410 __ dsubu(at, v0, at); // Sub as compare: at == 0 on eq. | 1410 __ dsubu(at, v0, at); // Sub as compare: at == 0 on eq. |
| 1411 if (var->mode() == LET || var->mode() == CONST) { | 1411 if (var->mode() == LET || var->mode() == CONST) { |
| 1412 // Throw a reference error when using an uninitialized let/const | 1412 // Throw a reference error when using an uninitialized let/const |
| 1413 // binding in harmony mode. | 1413 // binding in harmony mode. |
| 1414 Label done; | 1414 Label done; |
| 1415 __ Branch(&done, ne, at, Operand(zero_reg)); | 1415 __ Branch(&done, ne, at, Operand(zero_reg)); |
| 1416 __ li(a0, Operand(var->name())); | 1416 __ li(a0, Operand(var->name())); |
| 1417 __ push(a0); | 1417 __ push(a0); |
| 1418 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1418 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1419 __ bind(&done); | 1419 __ bind(&done); |
| 1420 } else { | 1420 } else { |
| 1421 // Uninitialized legacy const bindings are unholed. | 1421 // Uninitialized legacy const bindings are unholed. |
| 1422 DCHECK(var->mode() == CONST_LEGACY); | 1422 DCHECK(var->mode() == CONST_LEGACY); |
| 1423 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 1423 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
| 1424 __ Movz(v0, a0, at); // Conditional move: Undefined if TheHole. | 1424 __ Movz(v0, a0, at); // Conditional move: Undefined if TheHole. |
| 1425 } | 1425 } |
| 1426 context()->Plug(v0); | 1426 context()->Plug(v0); |
| 1427 break; | 1427 break; |
| 1428 } | 1428 } |
| 1429 context()->Plug(var); | 1429 context()->Plug(var); |
| 1430 break; | 1430 break; |
| 1431 } | 1431 } |
| 1432 | 1432 |
| 1433 case VariableLocation::LOOKUP: { | 1433 case VariableLocation::LOOKUP: { |
| 1434 Comment cmnt(masm_, "[ Lookup variable"); | 1434 Comment cmnt(masm_, "[ Lookup variable"); |
| 1435 Label done, slow; | 1435 Label done, slow; |
| 1436 // Generate code for loading from variables potentially shadowed | 1436 // Generate code for loading from variables potentially shadowed |
| 1437 // by eval-introduced variables. | 1437 // by eval-introduced variables. |
| 1438 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | 1438 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); |
| 1439 __ bind(&slow); | 1439 __ bind(&slow); |
| 1440 __ li(a1, Operand(var->name())); | 1440 __ li(a1, Operand(var->name())); |
| 1441 __ Push(cp, a1); // Context and name. | 1441 __ Push(cp, a1); // Context and name. |
| 1442 Runtime::FunctionId function_id = | 1442 Runtime::FunctionId function_id = |
| 1443 typeof_mode == NOT_INSIDE_TYPEOF | 1443 typeof_mode == NOT_INSIDE_TYPEOF |
| 1444 ? Runtime::kLoadLookupSlot | 1444 ? Runtime::kLoadLookupSlot |
| 1445 : Runtime::kLoadLookupSlotNoReferenceError; | 1445 : Runtime::kLoadLookupSlotNoReferenceError; |
| 1446 __ CallRuntime(function_id, 2); | 1446 __ CallRuntime(function_id); |
| 1447 __ bind(&done); | 1447 __ bind(&done); |
| 1448 context()->Plug(v0); | 1448 context()->Plug(v0); |
| 1449 } | 1449 } |
| 1450 } | 1450 } |
| 1451 } | 1451 } |
| 1452 | 1452 |
| 1453 | 1453 |
| 1454 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1454 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1455 Comment cmnt(masm_, "[ RegExpLiteral"); | 1455 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 1456 __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1456 __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1483 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 1483 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 1484 Comment cmnt(masm_, "[ ObjectLiteral"); | 1484 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 1485 | 1485 |
| 1486 Handle<FixedArray> constant_properties = expr->constant_properties(); | 1486 Handle<FixedArray> constant_properties = expr->constant_properties(); |
| 1487 __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1487 __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1488 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); | 1488 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1489 __ li(a1, Operand(constant_properties)); | 1489 __ li(a1, Operand(constant_properties)); |
| 1490 __ li(a0, Operand(Smi::FromInt(expr->ComputeFlags()))); | 1490 __ li(a0, Operand(Smi::FromInt(expr->ComputeFlags()))); |
| 1491 if (MustCreateObjectLiteralWithRuntime(expr)) { | 1491 if (MustCreateObjectLiteralWithRuntime(expr)) { |
| 1492 __ Push(a3, a2, a1, a0); | 1492 __ Push(a3, a2, a1, a0); |
| 1493 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1493 __ CallRuntime(Runtime::kCreateObjectLiteral); |
| 1494 } else { | 1494 } else { |
| 1495 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1495 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
| 1496 __ CallStub(&stub); | 1496 __ CallStub(&stub); |
| 1497 } | 1497 } |
| 1498 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1498 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
| 1499 | 1499 |
| 1500 // If result_saved is true the result is on top of the stack. If | 1500 // If result_saved is true the result is on top of the stack. If |
| 1501 // result_saved is false the result is in v0. | 1501 // result_saved is false the result is in v0. |
| 1502 bool result_saved = false; | 1502 bool result_saved = false; |
| 1503 | 1503 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1546 __ ld(a0, MemOperand(sp)); | 1546 __ ld(a0, MemOperand(sp)); |
| 1547 __ push(a0); | 1547 __ push(a0); |
| 1548 VisitForStackValue(key); | 1548 VisitForStackValue(key); |
| 1549 VisitForStackValue(value); | 1549 VisitForStackValue(value); |
| 1550 if (property->emit_store()) { | 1550 if (property->emit_store()) { |
| 1551 if (NeedsHomeObject(value)) { | 1551 if (NeedsHomeObject(value)) { |
| 1552 EmitSetHomeObject(value, 2, property->GetSlot()); | 1552 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 1553 } | 1553 } |
| 1554 __ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes. | 1554 __ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes. |
| 1555 __ push(a0); | 1555 __ push(a0); |
| 1556 __ CallRuntime(Runtime::kSetProperty, 4); | 1556 __ CallRuntime(Runtime::kSetProperty); |
| 1557 } else { | 1557 } else { |
| 1558 __ Drop(3); | 1558 __ Drop(3); |
| 1559 } | 1559 } |
| 1560 break; | 1560 break; |
| 1561 case ObjectLiteral::Property::PROTOTYPE: | 1561 case ObjectLiteral::Property::PROTOTYPE: |
| 1562 // Duplicate receiver on stack. | 1562 // Duplicate receiver on stack. |
| 1563 __ ld(a0, MemOperand(sp)); | 1563 __ ld(a0, MemOperand(sp)); |
| 1564 __ push(a0); | 1564 __ push(a0); |
| 1565 VisitForStackValue(value); | 1565 VisitForStackValue(value); |
| 1566 DCHECK(property->emit_store()); | 1566 DCHECK(property->emit_store()); |
| 1567 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1567 __ CallRuntime(Runtime::kInternalSetPrototype); |
| 1568 break; | 1568 break; |
| 1569 case ObjectLiteral::Property::GETTER: | 1569 case ObjectLiteral::Property::GETTER: |
| 1570 if (property->emit_store()) { | 1570 if (property->emit_store()) { |
| 1571 accessor_table.lookup(key)->second->getter = property; | 1571 accessor_table.lookup(key)->second->getter = property; |
| 1572 } | 1572 } |
| 1573 break; | 1573 break; |
| 1574 case ObjectLiteral::Property::SETTER: | 1574 case ObjectLiteral::Property::SETTER: |
| 1575 if (property->emit_store()) { | 1575 if (property->emit_store()) { |
| 1576 accessor_table.lookup(key)->second->setter = property; | 1576 accessor_table.lookup(key)->second->setter = property; |
| 1577 } | 1577 } |
| 1578 break; | 1578 break; |
| 1579 } | 1579 } |
| 1580 } | 1580 } |
| 1581 | 1581 |
| 1582 // Emit code to define accessors, using only a single call to the runtime for | 1582 // Emit code to define accessors, using only a single call to the runtime for |
| 1583 // each pair of corresponding getters and setters. | 1583 // each pair of corresponding getters and setters. |
| 1584 for (AccessorTable::Iterator it = accessor_table.begin(); | 1584 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 1585 it != accessor_table.end(); | 1585 it != accessor_table.end(); |
| 1586 ++it) { | 1586 ++it) { |
| 1587 __ ld(a0, MemOperand(sp)); // Duplicate receiver. | 1587 __ ld(a0, MemOperand(sp)); // Duplicate receiver. |
| 1588 __ push(a0); | 1588 __ push(a0); |
| 1589 VisitForStackValue(it->first); | 1589 VisitForStackValue(it->first); |
| 1590 EmitAccessor(it->second->getter); | 1590 EmitAccessor(it->second->getter); |
| 1591 EmitAccessor(it->second->setter); | 1591 EmitAccessor(it->second->setter); |
| 1592 __ li(a0, Operand(Smi::FromInt(NONE))); | 1592 __ li(a0, Operand(Smi::FromInt(NONE))); |
| 1593 __ push(a0); | 1593 __ push(a0); |
| 1594 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1594 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); |
| 1595 } | 1595 } |
| 1596 | 1596 |
| 1597 // Object literals have two parts. The "static" part on the left contains no | 1597 // Object literals have two parts. The "static" part on the left contains no |
| 1598 // computed property names, and so we can compute its map ahead of time; see | 1598 // computed property names, and so we can compute its map ahead of time; see |
| 1599 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part | 1599 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
| 1600 // starts with the first computed property name, and continues with all | 1600 // starts with the first computed property name, and continues with all |
| 1601 // properties to its right. All the code from above initializes the static | 1601 // properties to its right. All the code from above initializes the static |
| 1602 // component of the object literal, and arranges for the map of the result to | 1602 // component of the object literal, and arranges for the map of the result to |
| 1603 // reflect the static order in which the keys appear. For the dynamic | 1603 // reflect the static order in which the keys appear. For the dynamic |
| 1604 // properties, we compile them into a series of "SetOwnProperty" runtime | 1604 // properties, we compile them into a series of "SetOwnProperty" runtime |
| 1605 // calls. This will preserve insertion order. | 1605 // calls. This will preserve insertion order. |
| 1606 for (; property_index < expr->properties()->length(); property_index++) { | 1606 for (; property_index < expr->properties()->length(); property_index++) { |
| 1607 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1607 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1608 | 1608 |
| 1609 Expression* value = property->value(); | 1609 Expression* value = property->value(); |
| 1610 if (!result_saved) { | 1610 if (!result_saved) { |
| 1611 __ push(v0); // Save result on the stack | 1611 __ push(v0); // Save result on the stack |
| 1612 result_saved = true; | 1612 result_saved = true; |
| 1613 } | 1613 } |
| 1614 | 1614 |
| 1615 __ ld(a0, MemOperand(sp)); // Duplicate receiver. | 1615 __ ld(a0, MemOperand(sp)); // Duplicate receiver. |
| 1616 __ push(a0); | 1616 __ push(a0); |
| 1617 | 1617 |
| 1618 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1618 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
| 1619 DCHECK(!property->is_computed_name()); | 1619 DCHECK(!property->is_computed_name()); |
| 1620 VisitForStackValue(value); | 1620 VisitForStackValue(value); |
| 1621 DCHECK(property->emit_store()); | 1621 DCHECK(property->emit_store()); |
| 1622 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1622 __ CallRuntime(Runtime::kInternalSetPrototype); |
| 1623 } else { | 1623 } else { |
| 1624 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); | 1624 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); |
| 1625 VisitForStackValue(value); | 1625 VisitForStackValue(value); |
| 1626 if (NeedsHomeObject(value)) { | 1626 if (NeedsHomeObject(value)) { |
| 1627 EmitSetHomeObject(value, 2, property->GetSlot()); | 1627 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 1628 } | 1628 } |
| 1629 | 1629 |
| 1630 switch (property->kind()) { | 1630 switch (property->kind()) { |
| 1631 case ObjectLiteral::Property::CONSTANT: | 1631 case ObjectLiteral::Property::CONSTANT: |
| 1632 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1632 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1633 case ObjectLiteral::Property::COMPUTED: | 1633 case ObjectLiteral::Property::COMPUTED: |
| 1634 if (property->emit_store()) { | 1634 if (property->emit_store()) { |
| 1635 __ li(a0, Operand(Smi::FromInt(NONE))); | 1635 __ li(a0, Operand(Smi::FromInt(NONE))); |
| 1636 __ push(a0); | 1636 __ push(a0); |
| 1637 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); | 1637 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked); |
| 1638 } else { | 1638 } else { |
| 1639 __ Drop(3); | 1639 __ Drop(3); |
| 1640 } | 1640 } |
| 1641 break; | 1641 break; |
| 1642 | 1642 |
| 1643 case ObjectLiteral::Property::PROTOTYPE: | 1643 case ObjectLiteral::Property::PROTOTYPE: |
| 1644 UNREACHABLE(); | 1644 UNREACHABLE(); |
| 1645 break; | 1645 break; |
| 1646 | 1646 |
| 1647 case ObjectLiteral::Property::GETTER: | 1647 case ObjectLiteral::Property::GETTER: |
| 1648 __ li(a0, Operand(Smi::FromInt(NONE))); | 1648 __ li(a0, Operand(Smi::FromInt(NONE))); |
| 1649 __ push(a0); | 1649 __ push(a0); |
| 1650 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 1650 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
| 1651 break; | 1651 break; |
| 1652 | 1652 |
| 1653 case ObjectLiteral::Property::SETTER: | 1653 case ObjectLiteral::Property::SETTER: |
| 1654 __ li(a0, Operand(Smi::FromInt(NONE))); | 1654 __ li(a0, Operand(Smi::FromInt(NONE))); |
| 1655 __ push(a0); | 1655 __ push(a0); |
| 1656 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 1656 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
| 1657 break; | 1657 break; |
| 1658 } | 1658 } |
| 1659 } | 1659 } |
| 1660 } | 1660 } |
| 1661 | 1661 |
| 1662 if (expr->has_function()) { | 1662 if (expr->has_function()) { |
| 1663 DCHECK(result_saved); | 1663 DCHECK(result_saved); |
| 1664 __ ld(a0, MemOperand(sp)); | 1664 __ ld(a0, MemOperand(sp)); |
| 1665 __ push(a0); | 1665 __ push(a0); |
| 1666 __ CallRuntime(Runtime::kToFastProperties, 1); | 1666 __ CallRuntime(Runtime::kToFastProperties); |
| 1667 } | 1667 } |
| 1668 | 1668 |
| 1669 if (result_saved) { | 1669 if (result_saved) { |
| 1670 context()->PlugTOS(); | 1670 context()->PlugTOS(); |
| 1671 } else { | 1671 } else { |
| 1672 context()->Plug(v0); | 1672 context()->Plug(v0); |
| 1673 } | 1673 } |
| 1674 } | 1674 } |
| 1675 | 1675 |
| 1676 | 1676 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1688 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1688 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
| 1689 } | 1689 } |
| 1690 | 1690 |
| 1691 __ mov(a0, result_register()); | 1691 __ mov(a0, result_register()); |
| 1692 __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1692 __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1693 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); | 1693 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1694 __ li(a1, Operand(constant_elements)); | 1694 __ li(a1, Operand(constant_elements)); |
| 1695 if (MustCreateArrayLiteralWithRuntime(expr)) { | 1695 if (MustCreateArrayLiteralWithRuntime(expr)) { |
| 1696 __ li(a0, Operand(Smi::FromInt(expr->ComputeFlags()))); | 1696 __ li(a0, Operand(Smi::FromInt(expr->ComputeFlags()))); |
| 1697 __ Push(a3, a2, a1, a0); | 1697 __ Push(a3, a2, a1, a0); |
| 1698 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); | 1698 __ CallRuntime(Runtime::kCreateArrayLiteral); |
| 1699 } else { | 1699 } else { |
| 1700 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1700 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
| 1701 __ CallStub(&stub); | 1701 __ CallStub(&stub); |
| 1702 } | 1702 } |
| 1703 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1703 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
| 1704 | 1704 |
| 1705 bool result_saved = false; // Is the result saved to the stack? | 1705 bool result_saved = false; // Is the result saved to the stack? |
| 1706 ZoneList<Expression*>* subexprs = expr->values(); | 1706 ZoneList<Expression*>* subexprs = expr->values(); |
| 1707 int length = subexprs->length(); | 1707 int length = subexprs->length(); |
| 1708 | 1708 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1747 for (; array_index < length; array_index++) { | 1747 for (; array_index < length; array_index++) { |
| 1748 Expression* subexpr = subexprs->at(array_index); | 1748 Expression* subexpr = subexprs->at(array_index); |
| 1749 | 1749 |
| 1750 __ Push(v0); | 1750 __ Push(v0); |
| 1751 if (subexpr->IsSpread()) { | 1751 if (subexpr->IsSpread()) { |
| 1752 VisitForStackValue(subexpr->AsSpread()->expression()); | 1752 VisitForStackValue(subexpr->AsSpread()->expression()); |
| 1753 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, | 1753 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, |
| 1754 CALL_FUNCTION); | 1754 CALL_FUNCTION); |
| 1755 } else { | 1755 } else { |
| 1756 VisitForStackValue(subexpr); | 1756 VisitForStackValue(subexpr); |
| 1757 __ CallRuntime(Runtime::kAppendElement, 2); | 1757 __ CallRuntime(Runtime::kAppendElement); |
| 1758 } | 1758 } |
| 1759 | 1759 |
| 1760 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); | 1760 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
| 1761 } | 1761 } |
| 1762 | 1762 |
| 1763 if (result_saved) { | 1763 if (result_saved) { |
| 1764 context()->PlugTOS(); | 1764 context()->PlugTOS(); |
| 1765 } else { | 1765 } else { |
| 1766 context()->Plug(v0); | 1766 context()->Plug(v0); |
| 1767 } | 1767 } |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2152 Label push_operand_holes, call_resume; | 2152 Label push_operand_holes, call_resume; |
| 2153 __ bind(&push_operand_holes); | 2153 __ bind(&push_operand_holes); |
| 2154 __ Dsubu(a3, a3, Operand(1)); | 2154 __ Dsubu(a3, a3, Operand(1)); |
| 2155 __ Branch(&call_resume, lt, a3, Operand(zero_reg)); | 2155 __ Branch(&call_resume, lt, a3, Operand(zero_reg)); |
| 2156 __ push(a2); | 2156 __ push(a2); |
| 2157 __ Branch(&push_operand_holes); | 2157 __ Branch(&push_operand_holes); |
| 2158 __ bind(&call_resume); | 2158 __ bind(&call_resume); |
| 2159 DCHECK(!result_register().is(a1)); | 2159 DCHECK(!result_register().is(a1)); |
| 2160 __ Push(a1, result_register()); | 2160 __ Push(a1, result_register()); |
| 2161 __ Push(Smi::FromInt(resume_mode)); | 2161 __ Push(Smi::FromInt(resume_mode)); |
| 2162 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2162 __ CallRuntime(Runtime::kResumeJSGeneratorObject); |
| 2163 // Not reached: the runtime call returns elsewhere. | 2163 // Not reached: the runtime call returns elsewhere. |
| 2164 __ stop("not-reached"); | 2164 __ stop("not-reached"); |
| 2165 | 2165 |
| 2166 __ bind(&done); | 2166 __ bind(&done); |
| 2167 context()->Plug(result_register()); | 2167 context()->Plug(result_register()); |
| 2168 } | 2168 } |
| 2169 | 2169 |
| 2170 | 2170 |
| 2171 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2171 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| 2172 Label allocate, done_allocate; | 2172 Label allocate, done_allocate; |
| 2173 | 2173 |
| 2174 __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &allocate, TAG_OBJECT); | 2174 __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &allocate, TAG_OBJECT); |
| 2175 __ jmp(&done_allocate); | 2175 __ jmp(&done_allocate); |
| 2176 | 2176 |
| 2177 __ bind(&allocate); | 2177 __ bind(&allocate); |
| 2178 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 2178 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
| 2179 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2179 __ CallRuntime(Runtime::kAllocateInNewSpace); |
| 2180 | 2180 |
| 2181 __ bind(&done_allocate); | 2181 __ bind(&done_allocate); |
| 2182 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, a1); | 2182 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, a1); |
| 2183 __ pop(a2); | 2183 __ pop(a2); |
| 2184 __ LoadRoot(a3, | 2184 __ LoadRoot(a3, |
| 2185 done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); | 2185 done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); |
| 2186 __ LoadRoot(a4, Heap::kEmptyFixedArrayRootIndex); | 2186 __ LoadRoot(a4, Heap::kEmptyFixedArrayRootIndex); |
| 2187 __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); | 2187 __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); |
| 2188 __ sd(a4, FieldMemOperand(v0, JSObject::kPropertiesOffset)); | 2188 __ sd(a4, FieldMemOperand(v0, JSObject::kPropertiesOffset)); |
| 2189 __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset)); | 2189 __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2208 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { | 2208 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
| 2209 // Stack: receiver, home_object. | 2209 // Stack: receiver, home_object. |
| 2210 SetExpressionPosition(prop); | 2210 SetExpressionPosition(prop); |
| 2211 | 2211 |
| 2212 Literal* key = prop->key()->AsLiteral(); | 2212 Literal* key = prop->key()->AsLiteral(); |
| 2213 DCHECK(!key->value()->IsSmi()); | 2213 DCHECK(!key->value()->IsSmi()); |
| 2214 DCHECK(prop->IsSuperAccess()); | 2214 DCHECK(prop->IsSuperAccess()); |
| 2215 | 2215 |
| 2216 __ Push(key->value()); | 2216 __ Push(key->value()); |
| 2217 __ Push(Smi::FromInt(language_mode())); | 2217 __ Push(Smi::FromInt(language_mode())); |
| 2218 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2218 __ CallRuntime(Runtime::kLoadFromSuper); |
| 2219 } | 2219 } |
| 2220 | 2220 |
| 2221 | 2221 |
| 2222 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2222 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2223 // Call keyed load IC. It has register arguments receiver and key. | 2223 // Call keyed load IC. It has register arguments receiver and key. |
| 2224 SetExpressionPosition(prop); | 2224 SetExpressionPosition(prop); |
| 2225 | 2225 |
| 2226 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); | 2226 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); |
| 2227 __ li(LoadDescriptor::SlotRegister(), | 2227 __ li(LoadDescriptor::SlotRegister(), |
| 2228 Operand(SmiFromSlot(prop->PropertyFeedbackSlot()))); | 2228 Operand(SmiFromSlot(prop->PropertyFeedbackSlot()))); |
| 2229 CallIC(ic); | 2229 CallIC(ic); |
| 2230 } | 2230 } |
| 2231 | 2231 |
| 2232 | 2232 |
| 2233 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { | 2233 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
| 2234 // Stack: receiver, home_object, key. | 2234 // Stack: receiver, home_object, key. |
| 2235 SetExpressionPosition(prop); | 2235 SetExpressionPosition(prop); |
| 2236 __ Push(Smi::FromInt(language_mode())); | 2236 __ Push(Smi::FromInt(language_mode())); |
| 2237 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2237 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
| 2238 } | 2238 } |
| 2239 | 2239 |
| 2240 | 2240 |
| 2241 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2241 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2242 Token::Value op, | 2242 Token::Value op, |
| 2243 Expression* left_expr, | 2243 Expression* left_expr, |
| 2244 Expression* right_expr) { | 2244 Expression* right_expr) { |
| 2245 Label done, smi_case, stub_call; | 2245 Label done, smi_case, stub_call; |
| 2246 | 2246 |
| 2247 Register scratch1 = a2; | 2247 Register scratch1 = a2; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2352 __ ld(scratch, MemOperand(sp, 0)); // prototype | 2352 __ ld(scratch, MemOperand(sp, 0)); // prototype |
| 2353 } | 2353 } |
| 2354 __ push(scratch); | 2354 __ push(scratch); |
| 2355 EmitPropertyKey(property, lit->GetIdForProperty(i)); | 2355 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
| 2356 | 2356 |
| 2357 // The static prototype property is read only. We handle the non computed | 2357 // The static prototype property is read only. We handle the non computed |
| 2358 // property name case in the parser. Since this is the only case where we | 2358 // property name case in the parser. Since this is the only case where we |
| 2359 // need to check for an own read only property we special case this so we do | 2359 // need to check for an own read only property we special case this so we do |
| 2360 // not need to do this for every property. | 2360 // not need to do this for every property. |
| 2361 if (property->is_static() && property->is_computed_name()) { | 2361 if (property->is_static() && property->is_computed_name()) { |
| 2362 __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1); | 2362 __ CallRuntime(Runtime::kThrowIfStaticPrototype); |
| 2363 __ push(v0); | 2363 __ push(v0); |
| 2364 } | 2364 } |
| 2365 | 2365 |
| 2366 VisitForStackValue(value); | 2366 VisitForStackValue(value); |
| 2367 if (NeedsHomeObject(value)) { | 2367 if (NeedsHomeObject(value)) { |
| 2368 EmitSetHomeObject(value, 2, property->GetSlot()); | 2368 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 2369 } | 2369 } |
| 2370 | 2370 |
| 2371 switch (property->kind()) { | 2371 switch (property->kind()) { |
| 2372 case ObjectLiteral::Property::CONSTANT: | 2372 case ObjectLiteral::Property::CONSTANT: |
| 2373 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2373 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 2374 case ObjectLiteral::Property::PROTOTYPE: | 2374 case ObjectLiteral::Property::PROTOTYPE: |
| 2375 UNREACHABLE(); | 2375 UNREACHABLE(); |
| 2376 case ObjectLiteral::Property::COMPUTED: | 2376 case ObjectLiteral::Property::COMPUTED: |
| 2377 __ CallRuntime(Runtime::kDefineClassMethod, 3); | 2377 __ CallRuntime(Runtime::kDefineClassMethod); |
| 2378 break; | 2378 break; |
| 2379 | 2379 |
| 2380 case ObjectLiteral::Property::GETTER: | 2380 case ObjectLiteral::Property::GETTER: |
| 2381 __ li(a0, Operand(Smi::FromInt(DONT_ENUM))); | 2381 __ li(a0, Operand(Smi::FromInt(DONT_ENUM))); |
| 2382 __ push(a0); | 2382 __ push(a0); |
| 2383 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 2383 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
| 2384 break; | 2384 break; |
| 2385 | 2385 |
| 2386 case ObjectLiteral::Property::SETTER: | 2386 case ObjectLiteral::Property::SETTER: |
| 2387 __ li(a0, Operand(Smi::FromInt(DONT_ENUM))); | 2387 __ li(a0, Operand(Smi::FromInt(DONT_ENUM))); |
| 2388 __ push(a0); | 2388 __ push(a0); |
| 2389 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 2389 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
| 2390 break; | 2390 break; |
| 2391 | 2391 |
| 2392 default: | 2392 default: |
| 2393 UNREACHABLE(); | 2393 UNREACHABLE(); |
| 2394 } | 2394 } |
| 2395 } | 2395 } |
| 2396 | 2396 |
| 2397 // Set both the prototype and constructor to have fast properties, and also | 2397 // Set both the prototype and constructor to have fast properties, and also |
| 2398 // freeze them in strong mode. | 2398 // freeze them in strong mode. |
| 2399 __ CallRuntime(Runtime::kFinalizeClassDefinition, 2); | 2399 __ CallRuntime(Runtime::kFinalizeClassDefinition); |
| 2400 } | 2400 } |
| 2401 | 2401 |
| 2402 | 2402 |
| 2403 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { | 2403 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
| 2404 __ mov(a0, result_register()); | 2404 __ mov(a0, result_register()); |
| 2405 __ pop(a1); | 2405 __ pop(a1); |
| 2406 Handle<Code> code = | 2406 Handle<Code> code = |
| 2407 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); | 2407 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); |
| 2408 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2408 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2409 CallIC(code, expr->BinaryOperationFeedbackId()); | 2409 CallIC(code, expr->BinaryOperationFeedbackId()); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2519 // Non-initializing assignment to let variable needs a write barrier. | 2519 // Non-initializing assignment to let variable needs a write barrier. |
| 2520 DCHECK(!var->IsLookupSlot()); | 2520 DCHECK(!var->IsLookupSlot()); |
| 2521 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2521 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2522 Label assign; | 2522 Label assign; |
| 2523 MemOperand location = VarOperand(var, a1); | 2523 MemOperand location = VarOperand(var, a1); |
| 2524 __ ld(a3, location); | 2524 __ ld(a3, location); |
| 2525 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); | 2525 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); |
| 2526 __ Branch(&assign, ne, a3, Operand(a4)); | 2526 __ Branch(&assign, ne, a3, Operand(a4)); |
| 2527 __ li(a3, Operand(var->name())); | 2527 __ li(a3, Operand(var->name())); |
| 2528 __ push(a3); | 2528 __ push(a3); |
| 2529 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2529 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2530 // Perform the assignment. | 2530 // Perform the assignment. |
| 2531 __ bind(&assign); | 2531 __ bind(&assign); |
| 2532 EmitStoreToStackLocalOrContextSlot(var, location); | 2532 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2533 | 2533 |
| 2534 } else if (var->mode() == CONST && op != Token::INIT) { | 2534 } else if (var->mode() == CONST && op != Token::INIT) { |
| 2535 // Assignment to const variable needs a write barrier. | 2535 // Assignment to const variable needs a write barrier. |
| 2536 DCHECK(!var->IsLookupSlot()); | 2536 DCHECK(!var->IsLookupSlot()); |
| 2537 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2537 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2538 Label const_error; | 2538 Label const_error; |
| 2539 MemOperand location = VarOperand(var, a1); | 2539 MemOperand location = VarOperand(var, a1); |
| 2540 __ ld(a3, location); | 2540 __ ld(a3, location); |
| 2541 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2541 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2542 __ Branch(&const_error, ne, a3, Operand(at)); | 2542 __ Branch(&const_error, ne, a3, Operand(at)); |
| 2543 __ li(a3, Operand(var->name())); | 2543 __ li(a3, Operand(var->name())); |
| 2544 __ push(a3); | 2544 __ push(a3); |
| 2545 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2545 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2546 __ bind(&const_error); | 2546 __ bind(&const_error); |
| 2547 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2547 __ CallRuntime(Runtime::kThrowConstAssignError); |
| 2548 | 2548 |
| 2549 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | 2549 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
| 2550 // Initializing assignment to const {this} needs a write barrier. | 2550 // Initializing assignment to const {this} needs a write barrier. |
| 2551 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2551 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2552 Label uninitialized_this; | 2552 Label uninitialized_this; |
| 2553 MemOperand location = VarOperand(var, a1); | 2553 MemOperand location = VarOperand(var, a1); |
| 2554 __ ld(a3, location); | 2554 __ ld(a3, location); |
| 2555 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2555 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2556 __ Branch(&uninitialized_this, eq, a3, Operand(at)); | 2556 __ Branch(&uninitialized_this, eq, a3, Operand(at)); |
| 2557 __ li(a0, Operand(var->name())); | 2557 __ li(a0, Operand(var->name())); |
| 2558 __ Push(a0); | 2558 __ Push(a0); |
| 2559 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2559 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2560 __ bind(&uninitialized_this); | 2560 __ bind(&uninitialized_this); |
| 2561 EmitStoreToStackLocalOrContextSlot(var, location); | 2561 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2562 | 2562 |
| 2563 } else if (!var->is_const_mode() || | 2563 } else if (!var->is_const_mode() || |
| 2564 (var->mode() == CONST && op == Token::INIT)) { | 2564 (var->mode() == CONST && op == Token::INIT)) { |
| 2565 if (var->IsLookupSlot()) { | 2565 if (var->IsLookupSlot()) { |
| 2566 // Assignment to var. | 2566 // Assignment to var. |
| 2567 __ li(a4, Operand(var->name())); | 2567 __ li(a4, Operand(var->name())); |
| 2568 __ li(a3, Operand(Smi::FromInt(language_mode()))); | 2568 __ li(a3, Operand(Smi::FromInt(language_mode()))); |
| 2569 // jssp[0] : language mode. | 2569 // jssp[0] : language mode. |
| 2570 // jssp[8] : name. | 2570 // jssp[8] : name. |
| 2571 // jssp[16] : context. | 2571 // jssp[16] : context. |
| 2572 // jssp[24] : value. | 2572 // jssp[24] : value. |
| 2573 __ Push(v0, cp, a4, a3); | 2573 __ Push(v0, cp, a4, a3); |
| 2574 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2574 __ CallRuntime(Runtime::kStoreLookupSlot); |
| 2575 } else { | 2575 } else { |
| 2576 // Assignment to var or initializing assignment to let/const in harmony | 2576 // Assignment to var or initializing assignment to let/const in harmony |
| 2577 // mode. | 2577 // mode. |
| 2578 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 2578 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
| 2579 MemOperand location = VarOperand(var, a1); | 2579 MemOperand location = VarOperand(var, a1); |
| 2580 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { | 2580 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { |
| 2581 // Check for an uninitialized let binding. | 2581 // Check for an uninitialized let binding. |
| 2582 __ ld(a2, location); | 2582 __ ld(a2, location); |
| 2583 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); | 2583 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); |
| 2584 __ Check(eq, kLetBindingReInitialization, a2, Operand(a4)); | 2584 __ Check(eq, kLetBindingReInitialization, a2, Operand(a4)); |
| 2585 } | 2585 } |
| 2586 EmitStoreToStackLocalOrContextSlot(var, location); | 2586 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2587 } | 2587 } |
| 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 __ li(a0, Operand(var->name())); | 2593 __ li(a0, Operand(var->name())); |
| 2594 __ Push(v0, cp, a0); // Context and name. | 2594 __ Push(v0, cp, a0); // Context and name. |
| 2595 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2595 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot); |
| 2596 } else { | 2596 } else { |
| 2597 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2597 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2598 Label skip; | 2598 Label skip; |
| 2599 MemOperand location = VarOperand(var, a1); | 2599 MemOperand location = VarOperand(var, a1); |
| 2600 __ ld(a2, location); | 2600 __ ld(a2, location); |
| 2601 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2601 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2602 __ Branch(&skip, ne, a2, Operand(at)); | 2602 __ Branch(&skip, ne, a2, Operand(at)); |
| 2603 EmitStoreToStackLocalOrContextSlot(var, location); | 2603 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2604 __ bind(&skip); | 2604 __ bind(&skip); |
| 2605 } | 2605 } |
| 2606 | 2606 |
| 2607 } else { | 2607 } else { |
| 2608 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); | 2608 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); |
| 2609 if (is_strict(language_mode())) { | 2609 if (is_strict(language_mode())) { |
| 2610 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2610 __ CallRuntime(Runtime::kThrowConstAssignError); |
| 2611 } | 2611 } |
| 2612 // Silently ignore store in sloppy mode. | 2612 // Silently ignore store in sloppy mode. |
| 2613 } | 2613 } |
| 2614 } | 2614 } |
| 2615 | 2615 |
| 2616 | 2616 |
| 2617 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2617 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2618 // Assignment to a property, using a named store IC. | 2618 // Assignment to a property, using a named store IC. |
| 2619 Property* prop = expr->target()->AsProperty(); | 2619 Property* prop = expr->target()->AsProperty(); |
| 2620 DCHECK(prop != NULL); | 2620 DCHECK(prop != NULL); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2636 // Assignment to named property of super. | 2636 // Assignment to named property of super. |
| 2637 // v0 : value | 2637 // v0 : 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(v0); | 2644 __ Push(v0); |
| 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 // v0 : value | 2652 // v0 : 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(v0); | 2656 __ Push(v0); |
| 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 // Call keyed store IC. | 2665 // Call keyed store IC. |
| 2668 // The arguments are: | 2666 // The arguments are: |
| 2669 // - a0 is the value, | 2667 // - a0 is the value, |
| 2670 // - a1 is the key, | 2668 // - a1 is the key, |
| 2671 // - a2 is the receiver. | 2669 // - a2 is the receiver. |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2780 __ Push(key->value()); | 2778 __ Push(key->value()); |
| 2781 __ Push(Smi::FromInt(language_mode())); | 2779 __ Push(Smi::FromInt(language_mode())); |
| 2782 | 2780 |
| 2783 // Stack here: | 2781 // Stack here: |
| 2784 // - home_object | 2782 // - home_object |
| 2785 // - this (receiver) | 2783 // - this (receiver) |
| 2786 // - this (receiver) <-- LoadFromSuper will pop here and below. | 2784 // - this (receiver) <-- LoadFromSuper will pop here and below. |
| 2787 // - home_object | 2785 // - home_object |
| 2788 // - key | 2786 // - key |
| 2789 // - language_mode | 2787 // - language_mode |
| 2790 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2788 __ CallRuntime(Runtime::kLoadFromSuper); |
| 2791 | 2789 |
| 2792 // Replace home_object with target function. | 2790 // Replace home_object with target function. |
| 2793 __ sd(v0, MemOperand(sp, kPointerSize)); | 2791 __ sd(v0, MemOperand(sp, kPointerSize)); |
| 2794 | 2792 |
| 2795 // Stack here: | 2793 // Stack here: |
| 2796 // - target function | 2794 // - target function |
| 2797 // - this (receiver) | 2795 // - this (receiver) |
| 2798 EmitCall(expr); | 2796 EmitCall(expr); |
| 2799 } | 2797 } |
| 2800 | 2798 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2840 VisitForStackValue(prop->key()); | 2838 VisitForStackValue(prop->key()); |
| 2841 __ Push(Smi::FromInt(language_mode())); | 2839 __ Push(Smi::FromInt(language_mode())); |
| 2842 | 2840 |
| 2843 // Stack here: | 2841 // Stack here: |
| 2844 // - home_object | 2842 // - home_object |
| 2845 // - this (receiver) | 2843 // - this (receiver) |
| 2846 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. | 2844 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. |
| 2847 // - home_object | 2845 // - home_object |
| 2848 // - key | 2846 // - key |
| 2849 // - language_mode | 2847 // - language_mode |
| 2850 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2848 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
| 2851 | 2849 |
| 2852 // Replace home_object with target function. | 2850 // Replace home_object with target function. |
| 2853 __ sd(v0, MemOperand(sp, kPointerSize)); | 2851 __ sd(v0, MemOperand(sp, kPointerSize)); |
| 2854 | 2852 |
| 2855 // Stack here: | 2853 // Stack here: |
| 2856 // - target function | 2854 // - target function |
| 2857 // - this (receiver) | 2855 // - this (receiver) |
| 2858 EmitCall(expr); | 2856 EmitCall(expr); |
| 2859 } | 2857 } |
| 2860 | 2858 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2895 __ ld(a5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 2893 __ ld(a5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 2896 | 2894 |
| 2897 // a4: the language mode. | 2895 // a4: the language mode. |
| 2898 __ li(a4, Operand(Smi::FromInt(language_mode()))); | 2896 __ li(a4, Operand(Smi::FromInt(language_mode()))); |
| 2899 | 2897 |
| 2900 // a1: the start position of the scope the calls resides in. | 2898 // a1: the start position of the scope the calls resides in. |
| 2901 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); | 2899 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); |
| 2902 | 2900 |
| 2903 // Do the runtime call. | 2901 // Do the runtime call. |
| 2904 __ Push(a6, a5, a4, a1); | 2902 __ Push(a6, a5, a4, a1); |
| 2905 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2903 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); |
| 2906 } | 2904 } |
| 2907 | 2905 |
| 2908 | 2906 |
| 2909 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | 2907 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. |
| 2910 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | 2908 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
| 2911 VariableProxy* callee = expr->expression()->AsVariableProxy(); | 2909 VariableProxy* callee = expr->expression()->AsVariableProxy(); |
| 2912 if (callee->var()->IsLookupSlot()) { | 2910 if (callee->var()->IsLookupSlot()) { |
| 2913 Label slow, done; | 2911 Label slow, done; |
| 2914 | 2912 |
| 2915 SetExpressionPosition(callee); | 2913 SetExpressionPosition(callee); |
| 2916 // Generate code for loading from variables potentially shadowed by | 2914 // Generate code for loading from variables potentially shadowed by |
| 2917 // eval-introduced variables. | 2915 // eval-introduced variables. |
| 2918 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | 2916 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |
| 2919 | 2917 |
| 2920 __ bind(&slow); | 2918 __ bind(&slow); |
| 2921 // Call the runtime to find the function to call (returned in v0) | 2919 // Call the runtime to find the function to call (returned in v0) |
| 2922 // and the object holding it (returned in v1). | 2920 // and the object holding it (returned in v1). |
| 2923 DCHECK(!context_register().is(a2)); | 2921 DCHECK(!context_register().is(a2)); |
| 2924 __ li(a2, Operand(callee->name())); | 2922 __ li(a2, Operand(callee->name())); |
| 2925 __ Push(context_register(), a2); | 2923 __ Push(context_register(), a2); |
| 2926 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 2924 __ CallRuntime(Runtime::kLoadLookupSlot); |
| 2927 __ Push(v0, v1); // Function, receiver. | 2925 __ Push(v0, v1); // Function, receiver. |
| 2928 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); | 2926 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
| 2929 | 2927 |
| 2930 // If fast case code has been generated, emit code to push the | 2928 // If fast case code has been generated, emit code to push the |
| 2931 // function and receiver and have the slow path jump around this | 2929 // function and receiver and have the slow path jump around this |
| 2932 // code. | 2930 // code. |
| 2933 if (done.is_linked()) { | 2931 if (done.is_linked()) { |
| 2934 Label call; | 2932 Label call; |
| 2935 __ Branch(&call); | 2933 __ Branch(&call); |
| 2936 __ bind(&done); | 2934 __ bind(&done); |
| (...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3575 ZoneList<Expression*>* args = expr->arguments(); | 3573 ZoneList<Expression*>* args = expr->arguments(); |
| 3576 DCHECK_EQ(1, args->length()); | 3574 DCHECK_EQ(1, args->length()); |
| 3577 | 3575 |
| 3578 // Load the argument into v0 and convert it. | 3576 // Load the argument into v0 and convert it. |
| 3579 VisitForAccumulatorValue(args->at(0)); | 3577 VisitForAccumulatorValue(args->at(0)); |
| 3580 | 3578 |
| 3581 // Convert the object to an integer. | 3579 // Convert the object to an integer. |
| 3582 Label done_convert; | 3580 Label done_convert; |
| 3583 __ JumpIfSmi(v0, &done_convert); | 3581 __ JumpIfSmi(v0, &done_convert); |
| 3584 __ Push(v0); | 3582 __ Push(v0); |
| 3585 __ CallRuntime(Runtime::kToInteger, 1); | 3583 __ CallRuntime(Runtime::kToInteger); |
| 3586 __ bind(&done_convert); | 3584 __ bind(&done_convert); |
| 3587 context()->Plug(v0); | 3585 context()->Plug(v0); |
| 3588 } | 3586 } |
| 3589 | 3587 |
| 3590 | 3588 |
| 3591 void FullCodeGenerator::EmitToName(CallRuntime* expr) { | 3589 void FullCodeGenerator::EmitToName(CallRuntime* expr) { |
| 3592 ZoneList<Expression*>* args = expr->arguments(); | 3590 ZoneList<Expression*>* args = expr->arguments(); |
| 3593 DCHECK_EQ(1, args->length()); | 3591 DCHECK_EQ(1, args->length()); |
| 3594 | 3592 |
| 3595 // Load the argument into v0 and convert it. | 3593 // Load the argument into v0 and convert it. |
| 3596 VisitForAccumulatorValue(args->at(0)); | 3594 VisitForAccumulatorValue(args->at(0)); |
| 3597 | 3595 |
| 3598 Label convert, done_convert; | 3596 Label convert, done_convert; |
| 3599 __ JumpIfSmi(v0, &convert); | 3597 __ JumpIfSmi(v0, &convert); |
| 3600 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); | 3598 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); |
| 3601 __ GetObjectType(v0, a1, a1); | 3599 __ GetObjectType(v0, a1, a1); |
| 3602 __ Branch(&done_convert, le, a1, Operand(LAST_NAME_TYPE)); | 3600 __ Branch(&done_convert, le, a1, Operand(LAST_NAME_TYPE)); |
| 3603 __ bind(&convert); | 3601 __ bind(&convert); |
| 3604 __ Push(v0); | 3602 __ Push(v0); |
| 3605 __ CallRuntime(Runtime::kToName, 1); | 3603 __ CallRuntime(Runtime::kToName); |
| 3606 __ bind(&done_convert); | 3604 __ bind(&done_convert); |
| 3607 context()->Plug(v0); | 3605 context()->Plug(v0); |
| 3608 } | 3606 } |
| 3609 | 3607 |
| 3610 | 3608 |
| 3611 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3609 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
| 3612 ZoneList<Expression*>* args = expr->arguments(); | 3610 ZoneList<Expression*>* args = expr->arguments(); |
| 3613 DCHECK(args->length() == 1); | 3611 DCHECK(args->length() == 1); |
| 3614 | 3612 |
| 3615 VisitForAccumulatorValue(args->at(0)); | 3613 VisitForAccumulatorValue(args->at(0)); |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4051 __ LoadRoot(a4, Heap::kEmptyFixedArrayRootIndex); | 4049 __ LoadRoot(a4, Heap::kEmptyFixedArrayRootIndex); |
| 4052 __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); | 4050 __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); |
| 4053 __ sd(a4, FieldMemOperand(v0, JSObject::kPropertiesOffset)); | 4051 __ sd(a4, FieldMemOperand(v0, JSObject::kPropertiesOffset)); |
| 4054 __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset)); | 4052 __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset)); |
| 4055 __ sd(a2, FieldMemOperand(v0, JSIteratorResult::kValueOffset)); | 4053 __ sd(a2, FieldMemOperand(v0, JSIteratorResult::kValueOffset)); |
| 4056 __ sd(a3, FieldMemOperand(v0, JSIteratorResult::kDoneOffset)); | 4054 __ sd(a3, FieldMemOperand(v0, JSIteratorResult::kDoneOffset)); |
| 4057 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 4055 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
| 4058 __ jmp(&done); | 4056 __ jmp(&done); |
| 4059 | 4057 |
| 4060 __ bind(&runtime); | 4058 __ bind(&runtime); |
| 4061 __ CallRuntime(Runtime::kCreateIterResultObject, 2); | 4059 __ CallRuntime(Runtime::kCreateIterResultObject); |
| 4062 | 4060 |
| 4063 __ bind(&done); | 4061 __ bind(&done); |
| 4064 context()->Plug(v0); | 4062 context()->Plug(v0); |
| 4065 } | 4063 } |
| 4066 | 4064 |
| 4067 | 4065 |
| 4068 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 4066 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
| 4069 // Push undefined as the receiver. | 4067 // Push undefined as the receiver. |
| 4070 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 4068 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
| 4071 __ push(v0); | 4069 __ push(v0); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4143 case Token::DELETE: { | 4141 case Token::DELETE: { |
| 4144 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4142 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 4145 Property* property = expr->expression()->AsProperty(); | 4143 Property* property = expr->expression()->AsProperty(); |
| 4146 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4144 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 4147 | 4145 |
| 4148 if (property != NULL) { | 4146 if (property != NULL) { |
| 4149 VisitForStackValue(property->obj()); | 4147 VisitForStackValue(property->obj()); |
| 4150 VisitForStackValue(property->key()); | 4148 VisitForStackValue(property->key()); |
| 4151 __ CallRuntime(is_strict(language_mode()) | 4149 __ CallRuntime(is_strict(language_mode()) |
| 4152 ? Runtime::kDeleteProperty_Strict | 4150 ? Runtime::kDeleteProperty_Strict |
| 4153 : Runtime::kDeleteProperty_Sloppy, | 4151 : Runtime::kDeleteProperty_Sloppy); |
| 4154 2); | |
| 4155 context()->Plug(v0); | 4152 context()->Plug(v0); |
| 4156 } else if (proxy != NULL) { | 4153 } else if (proxy != NULL) { |
| 4157 Variable* var = proxy->var(); | 4154 Variable* var = proxy->var(); |
| 4158 // Delete of an unqualified identifier is disallowed in strict mode but | 4155 // Delete of an unqualified identifier is disallowed in strict mode but |
| 4159 // "delete this" is allowed. | 4156 // "delete this" is allowed. |
| 4160 bool is_this = var->HasThisName(isolate()); | 4157 bool is_this = var->HasThisName(isolate()); |
| 4161 DCHECK(is_sloppy(language_mode()) || is_this); | 4158 DCHECK(is_sloppy(language_mode()) || is_this); |
| 4162 if (var->IsUnallocatedOrGlobalSlot()) { | 4159 if (var->IsUnallocatedOrGlobalSlot()) { |
| 4163 __ LoadGlobalObject(a2); | 4160 __ LoadGlobalObject(a2); |
| 4164 __ li(a1, Operand(var->name())); | 4161 __ li(a1, Operand(var->name())); |
| 4165 __ Push(a2, a1); | 4162 __ Push(a2, a1); |
| 4166 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); | 4163 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
| 4167 context()->Plug(v0); | 4164 context()->Plug(v0); |
| 4168 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4165 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4169 // Result of deleting non-global, non-dynamic variables is false. | 4166 // Result of deleting non-global, non-dynamic variables is false. |
| 4170 // The subexpression does not have side effects. | 4167 // The subexpression does not have side effects. |
| 4171 context()->Plug(is_this); | 4168 context()->Plug(is_this); |
| 4172 } else { | 4169 } else { |
| 4173 // Non-global variable. Call the runtime to try to delete from the | 4170 // Non-global variable. Call the runtime to try to delete from the |
| 4174 // context where the variable was introduced. | 4171 // context where the variable was introduced. |
| 4175 DCHECK(!context_register().is(a2)); | 4172 DCHECK(!context_register().is(a2)); |
| 4176 __ li(a2, Operand(var->name())); | 4173 __ li(a2, Operand(var->name())); |
| 4177 __ Push(context_register(), a2); | 4174 __ Push(context_register(), a2); |
| 4178 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); | 4175 __ CallRuntime(Runtime::kDeleteLookupSlot); |
| 4179 context()->Plug(v0); | 4176 context()->Plug(v0); |
| 4180 } | 4177 } |
| 4181 } else { | 4178 } else { |
| 4182 // Result of deleting non-property, non-variable reference is true. | 4179 // Result of deleting non-property, non-variable reference is true. |
| 4183 // The subexpression may have side effects. | 4180 // The subexpression may have side effects. |
| 4184 VisitForEffect(expr->expression()); | 4181 VisitForEffect(expr->expression()); |
| 4185 context()->Plug(true); | 4182 context()->Plug(true); |
| 4186 } | 4183 } |
| 4187 break; | 4184 break; |
| 4188 } | 4185 } |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4603 Label* if_false = NULL; | 4600 Label* if_false = NULL; |
| 4604 Label* fall_through = NULL; | 4601 Label* fall_through = NULL; |
| 4605 context()->PrepareTest(&materialize_true, &materialize_false, | 4602 context()->PrepareTest(&materialize_true, &materialize_false, |
| 4606 &if_true, &if_false, &fall_through); | 4603 &if_true, &if_false, &fall_through); |
| 4607 | 4604 |
| 4608 Token::Value op = expr->op(); | 4605 Token::Value op = expr->op(); |
| 4609 VisitForStackValue(expr->left()); | 4606 VisitForStackValue(expr->left()); |
| 4610 switch (op) { | 4607 switch (op) { |
| 4611 case Token::IN: | 4608 case Token::IN: |
| 4612 VisitForStackValue(expr->right()); | 4609 VisitForStackValue(expr->right()); |
| 4613 __ CallRuntime(Runtime::kHasProperty, 2); | 4610 __ CallRuntime(Runtime::kHasProperty); |
| 4614 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 4611 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
| 4615 __ LoadRoot(a4, Heap::kTrueValueRootIndex); | 4612 __ LoadRoot(a4, Heap::kTrueValueRootIndex); |
| 4616 Split(eq, v0, Operand(a4), if_true, if_false, fall_through); | 4613 Split(eq, v0, Operand(a4), if_true, if_false, fall_through); |
| 4617 break; | 4614 break; |
| 4618 | 4615 |
| 4619 case Token::INSTANCEOF: { | 4616 case Token::INSTANCEOF: { |
| 4620 VisitForAccumulatorValue(expr->right()); | 4617 VisitForAccumulatorValue(expr->right()); |
| 4621 __ mov(a0, result_register()); | 4618 __ mov(a0, result_register()); |
| 4622 __ pop(a1); | 4619 __ pop(a1); |
| 4623 InstanceOfStub stub(isolate()); | 4620 InstanceOfStub stub(isolate()); |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4882 reinterpret_cast<uint64_t>( | 4879 reinterpret_cast<uint64_t>( |
| 4883 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4880 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4884 return OSR_AFTER_STACK_CHECK; | 4881 return OSR_AFTER_STACK_CHECK; |
| 4885 } | 4882 } |
| 4886 | 4883 |
| 4887 | 4884 |
| 4888 } // namespace internal | 4885 } // namespace internal |
| 4889 } // namespace v8 | 4886 } // namespace v8 |
| 4890 | 4887 |
| 4891 #endif // V8_TARGET_ARCH_MIPS64 | 4888 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |