OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 void KeyedLoadFieldStub::InitializeInterfaceDescriptor( | 159 void KeyedLoadFieldStub::InitializeInterfaceDescriptor( |
160 Isolate* isolate, | 160 Isolate* isolate, |
161 CodeStubInterfaceDescriptor* descriptor) { | 161 CodeStubInterfaceDescriptor* descriptor) { |
162 static Register registers[] = { a1 }; | 162 static Register registers[] = { a1 }; |
163 descriptor->register_param_count_ = 1; | 163 descriptor->register_param_count_ = 1; |
164 descriptor->register_params_ = registers; | 164 descriptor->register_params_ = registers; |
165 descriptor->deoptimization_handler_ = NULL; | 165 descriptor->deoptimization_handler_ = NULL; |
166 } | 166 } |
167 | 167 |
168 | 168 |
169 void KeyedArrayCallStub::InitializeInterfaceDescriptor( | |
170 Isolate* isolate, | |
171 CodeStubInterfaceDescriptor* descriptor) { | |
172 static Register registers[] = { a2 }; | |
173 descriptor->register_param_count_ = 1; | |
174 descriptor->register_params_ = registers; | |
175 descriptor->continuation_type_ = TAIL_CALL_CONTINUATION; | |
176 descriptor->handler_arguments_mode_ = PASS_ARGUMENTS; | |
177 descriptor->deoptimization_handler_ = | |
178 FUNCTION_ADDR(KeyedCallIC_MissFromStubFailure); | |
179 } | |
180 | |
181 | |
182 void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( | 169 void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( |
183 Isolate* isolate, | 170 Isolate* isolate, |
184 CodeStubInterfaceDescriptor* descriptor) { | 171 CodeStubInterfaceDescriptor* descriptor) { |
185 static Register registers[] = { a2, a1, a0 }; | 172 static Register registers[] = { a2, a1, a0 }; |
186 descriptor->register_param_count_ = 3; | 173 descriptor->register_param_count_ = 3; |
187 descriptor->register_params_ = registers; | 174 descriptor->register_params_ = registers; |
188 descriptor->deoptimization_handler_ = | 175 descriptor->deoptimization_handler_ = |
189 FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure); | 176 FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure); |
190 } | 177 } |
191 | 178 |
(...skipping 3048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3240 __ sw(a1, FieldMemOperand(a2, Cell::kValueOffset)); | 3227 __ sw(a1, FieldMemOperand(a2, Cell::kValueOffset)); |
3241 // No need for a write barrier here - cells are rescanned. | 3228 // No need for a write barrier here - cells are rescanned. |
3242 | 3229 |
3243 __ bind(&done); | 3230 __ bind(&done); |
3244 } | 3231 } |
3245 | 3232 |
3246 | 3233 |
3247 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3234 void CallFunctionStub::Generate(MacroAssembler* masm) { |
3248 // a1 : the function to call | 3235 // a1 : the function to call |
3249 // a2 : cache cell for call target | 3236 // a2 : cache cell for call target |
3250 Label slow, non_function; | 3237 Label slow, non_function, wrap, cont; |
3251 | 3238 |
3252 // Check that the function is really a JavaScript function. | 3239 if (NeedsChecks()) { |
3253 // a1: pushed function (to be verified) | 3240 // Check that the function is really a JavaScript function. |
3254 __ JumpIfSmi(a1, &non_function); | 3241 // a1: pushed function (to be verified) |
| 3242 __ JumpIfSmi(a1, &non_function); |
3255 | 3243 |
3256 // Goto slow case if we do not have a function. | 3244 // Goto slow case if we do not have a function. |
3257 __ GetObjectType(a1, a3, a3); | 3245 __ GetObjectType(a1, a3, a3); |
3258 __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE)); | 3246 __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE)); |
3259 | 3247 |
3260 if (RecordCallTarget()) { | 3248 if (RecordCallTarget()) { |
3261 GenerateRecordCallTarget(masm); | 3249 GenerateRecordCallTarget(masm); |
| 3250 } |
3262 } | 3251 } |
3263 | 3252 |
3264 // Fast-case: Invoke the function now. | 3253 // Fast-case: Invoke the function now. |
3265 // a1: pushed function | 3254 // a1: pushed function |
3266 ParameterCount actual(argc_); | 3255 ParameterCount actual(argc_); |
3267 | 3256 |
| 3257 if (CallAsMethod()) { |
| 3258 if (NeedsChecks()) { |
| 3259 // Do not transform the receiver for strict mode functions and natives. |
| 3260 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 3261 __ lw(a3, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset)); |
| 3262 int32_t strict_mode_function_mask = |
| 3263 1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize); |
| 3264 int32_t native_mask = 1 << (SharedFunctionInfo::kNative + kSmiTagSize); |
| 3265 __ And(at, a3, Operand(strict_mode_function_mask | native_mask)); |
| 3266 __ Branch(&cont, ne, at, Operand(zero_reg)); |
| 3267 } |
| 3268 |
| 3269 // Compute the receiver in non-strict mode. |
| 3270 __ lw(a2, MemOperand(sp, argc_ * kPointerSize)); |
| 3271 |
| 3272 if (NeedsChecks()) { |
| 3273 // a0: actual number of arguments |
| 3274 // a1: function |
| 3275 // a2: first argument |
| 3276 __ JumpIfSmi(a2, &wrap); |
| 3277 __ GetObjectType(a2, a3, a3); |
| 3278 __ Branch(&wrap, lt, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 3279 } else { |
| 3280 __ jmp(&wrap); |
| 3281 } |
| 3282 |
| 3283 __ bind(&cont); |
| 3284 } |
3268 __ InvokeFunction(a1, actual, JUMP_FUNCTION, NullCallWrapper()); | 3285 __ InvokeFunction(a1, actual, JUMP_FUNCTION, NullCallWrapper()); |
3269 | 3286 |
3270 // Slow-case: Non-function called. | 3287 if (NeedsChecks()) { |
3271 __ bind(&slow); | 3288 // Slow-case: Non-function called. |
3272 if (RecordCallTarget()) { | 3289 __ bind(&slow); |
3273 // If there is a call target cache, mark it megamorphic in the | 3290 if (RecordCallTarget()) { |
3274 // non-function case. MegamorphicSentinel is an immortal immovable | 3291 // If there is a call target cache, mark it megamorphic in the |
3275 // object (undefined) so no write barrier is needed. | 3292 // non-function case. MegamorphicSentinel is an immortal immovable |
3276 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), | 3293 // object (undefined) so no write barrier is needed. |
3277 masm->isolate()->heap()->undefined_value()); | 3294 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), |
3278 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 3295 masm->isolate()->heap()->undefined_value()); |
3279 __ sw(at, FieldMemOperand(a2, Cell::kValueOffset)); | 3296 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
3280 } | 3297 __ sw(at, FieldMemOperand(a2, Cell::kValueOffset)); |
3281 // Check for function proxy. | 3298 } |
3282 __ Branch(&non_function, ne, a3, Operand(JS_FUNCTION_PROXY_TYPE)); | 3299 // Check for function proxy. |
3283 __ push(a1); // Put proxy as additional argument. | 3300 __ Branch(&non_function, ne, a3, Operand(JS_FUNCTION_PROXY_TYPE)); |
3284 __ li(a0, Operand(argc_ + 1, RelocInfo::NONE32)); | 3301 __ push(a1); // Put proxy as additional argument. |
3285 __ li(a2, Operand(0, RelocInfo::NONE32)); | 3302 __ li(a0, Operand(argc_ + 1, RelocInfo::NONE32)); |
3286 __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY); | 3303 __ li(a2, Operand(0, RelocInfo::NONE32)); |
3287 { | 3304 __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY); |
3288 Handle<Code> adaptor = | 3305 { |
3289 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 3306 Handle<Code> adaptor = |
3290 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3307 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 3308 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
| 3309 } |
| 3310 |
| 3311 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 3312 // of the original receiver from the call site). |
| 3313 __ bind(&non_function); |
| 3314 __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); |
| 3315 __ li(a0, Operand(argc_)); // Set up the number of arguments. |
| 3316 __ li(a2, Operand(0, RelocInfo::NONE32)); |
| 3317 __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION); |
| 3318 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 3319 RelocInfo::CODE_TARGET); |
3291 } | 3320 } |
3292 | 3321 |
3293 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 3322 if (CallAsMethod()) { |
3294 // of the original receiver from the call site). | 3323 __ bind(&wrap); |
3295 __ bind(&non_function); | 3324 // Wrap the receiver and patch it back onto the stack. |
3296 __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); | 3325 { FrameScope frame_scope(masm, StackFrame::INTERNAL); |
3297 __ li(a0, Operand(argc_)); // Set up the number of arguments. | 3326 __ Push(a1, a2); |
3298 __ mov(a2, zero_reg); | 3327 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
3299 __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION); | 3328 __ pop(a1); |
3300 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 3329 } |
3301 RelocInfo::CODE_TARGET); | 3330 __ mov(a0, v0); |
| 3331 __ sw(a0, MemOperand(sp, argc_ * kPointerSize)); |
| 3332 __ jmp(&cont); |
| 3333 } |
3302 } | 3334 } |
3303 | 3335 |
3304 | 3336 |
3305 void CallConstructStub::Generate(MacroAssembler* masm) { | 3337 void CallConstructStub::Generate(MacroAssembler* masm) { |
3306 // a0 : number of arguments | 3338 // a0 : number of arguments |
3307 // a1 : the function to call | 3339 // a1 : the function to call |
3308 // a2 : cache cell for call target | 3340 // a2 : cache cell for call target |
3309 Label slow, non_function_call; | 3341 Label slow, non_function_call; |
3310 | 3342 |
3311 // Check that the function is not a smi. | 3343 // Check that the function is not a smi. |
(...skipping 1875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5187 if (function_mode_ == JS_FUNCTION_STUB_MODE) { | 5219 if (function_mode_ == JS_FUNCTION_STUB_MODE) { |
5188 __ Addu(a1, a1, Operand(1)); | 5220 __ Addu(a1, a1, Operand(1)); |
5189 } | 5221 } |
5190 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 5222 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
5191 __ sll(a1, a1, kPointerSizeLog2); | 5223 __ sll(a1, a1, kPointerSizeLog2); |
5192 __ Ret(USE_DELAY_SLOT); | 5224 __ Ret(USE_DELAY_SLOT); |
5193 __ Addu(sp, sp, a1); | 5225 __ Addu(sp, sp, a1); |
5194 } | 5226 } |
5195 | 5227 |
5196 | 5228 |
5197 void StubFailureTailCallTrampolineStub::Generate(MacroAssembler* masm) { | |
5198 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); | |
5199 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
5200 __ mov(a1, v0); | |
5201 int parameter_count_offset = | |
5202 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | |
5203 __ lw(a0, MemOperand(fp, parameter_count_offset)); | |
5204 // The parameter count above includes the receiver for the arguments passed to | |
5205 // the deoptimization handler. Subtract the receiver for the parameter count | |
5206 // for the call. | |
5207 __ Subu(a0, a0, 1); | |
5208 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | |
5209 ParameterCount argument_count(a0); | |
5210 __ InvokeFunction(a1, argument_count, JUMP_FUNCTION, NullCallWrapper()); | |
5211 } | |
5212 | |
5213 | |
5214 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 5229 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
5215 if (masm->isolate()->function_entry_hook() != NULL) { | 5230 if (masm->isolate()->function_entry_hook() != NULL) { |
5216 ProfileEntryHookStub stub; | 5231 ProfileEntryHookStub stub; |
5217 __ push(ra); | 5232 __ push(ra); |
5218 __ CallStub(&stub); | 5233 __ CallStub(&stub); |
5219 __ pop(ra); | 5234 __ pop(ra); |
5220 } | 5235 } |
5221 } | 5236 } |
5222 | 5237 |
5223 | 5238 |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5712 MemOperand(fp, 6 * kPointerSize), | 5727 MemOperand(fp, 6 * kPointerSize), |
5713 NULL); | 5728 NULL); |
5714 } | 5729 } |
5715 | 5730 |
5716 | 5731 |
5717 #undef __ | 5732 #undef __ |
5718 | 5733 |
5719 } } // namespace v8::internal | 5734 } } // namespace v8::internal |
5720 | 5735 |
5721 #endif // V8_TARGET_ARCH_MIPS | 5736 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |