| 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 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 Isolate* isolate = masm->isolate(); | 476 Isolate* isolate = masm->isolate(); |
| 490 isolate->counters()->code_stubs()->Increment(); | 477 isolate->counters()->code_stubs()->Increment(); |
| 491 | 478 |
| 492 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); | 479 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); |
| 493 int param_count = descriptor->register_param_count_; | 480 int param_count = descriptor->register_param_count_; |
| 494 { | 481 { |
| 495 // Call the runtime system in a fresh internal frame. | 482 // Call the runtime system in a fresh internal frame. |
| 496 FrameScope scope(masm, StackFrame::INTERNAL); | 483 FrameScope scope(masm, StackFrame::INTERNAL); |
| 497 ASSERT(descriptor->register_param_count_ == 0 || | 484 ASSERT(descriptor->register_param_count_ == 0 || |
| 498 a0.is(descriptor->register_params_[param_count - 1])); | 485 a0.is(descriptor->register_params_[param_count - 1])); |
| 499 // Push arguments | 486 // Push arguments, adjust sp. |
| 487 __ Subu(sp, sp, Operand(param_count * kPointerSize)); |
| 500 for (int i = 0; i < param_count; ++i) { | 488 for (int i = 0; i < param_count; ++i) { |
| 501 __ push(descriptor->register_params_[i]); | 489 // Store argument to stack. |
| 490 __ sw(descriptor->register_params_[i], |
| 491 MemOperand(sp, (param_count-1-i) * kPointerSize)); |
| 502 } | 492 } |
| 503 ExternalReference miss = descriptor->miss_handler(); | 493 ExternalReference miss = descriptor->miss_handler(); |
| 504 __ CallExternalReference(miss, descriptor->register_param_count_); | 494 __ CallExternalReference(miss, descriptor->register_param_count_); |
| 505 } | 495 } |
| 506 | 496 |
| 507 __ Ret(); | 497 __ Ret(); |
| 508 } | 498 } |
| 509 | 499 |
| 510 | 500 |
| 511 // Takes a Smi and converts to an IEEE 64 bit floating point value in two | 501 // Takes a Smi and converts to an IEEE 64 bit floating point value in two |
| (...skipping 2728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3240 __ sw(a1, FieldMemOperand(a2, Cell::kValueOffset)); | 3230 __ sw(a1, FieldMemOperand(a2, Cell::kValueOffset)); |
| 3241 // No need for a write barrier here - cells are rescanned. | 3231 // No need for a write barrier here - cells are rescanned. |
| 3242 | 3232 |
| 3243 __ bind(&done); | 3233 __ bind(&done); |
| 3244 } | 3234 } |
| 3245 | 3235 |
| 3246 | 3236 |
| 3247 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3237 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3248 // a1 : the function to call | 3238 // a1 : the function to call |
| 3249 // a2 : cache cell for call target | 3239 // a2 : cache cell for call target |
| 3250 Label slow, non_function; | 3240 Label slow, non_function, wrap, cont; |
| 3251 | 3241 |
| 3252 // Check that the function is really a JavaScript function. | 3242 if (NeedsChecks()) { |
| 3253 // a1: pushed function (to be verified) | 3243 // Check that the function is really a JavaScript function. |
| 3254 __ JumpIfSmi(a1, &non_function); | 3244 // a1: pushed function (to be verified) |
| 3245 __ JumpIfSmi(a1, &non_function); |
| 3255 | 3246 |
| 3256 // Goto slow case if we do not have a function. | 3247 // Goto slow case if we do not have a function. |
| 3257 __ GetObjectType(a1, a3, a3); | 3248 __ GetObjectType(a1, a3, a3); |
| 3258 __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE)); | 3249 __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE)); |
| 3259 | 3250 |
| 3260 if (RecordCallTarget()) { | 3251 if (RecordCallTarget()) { |
| 3261 GenerateRecordCallTarget(masm); | 3252 GenerateRecordCallTarget(masm); |
| 3253 } |
| 3262 } | 3254 } |
| 3263 | 3255 |
| 3264 // Fast-case: Invoke the function now. | 3256 // Fast-case: Invoke the function now. |
| 3265 // a1: pushed function | 3257 // a1: pushed function |
| 3266 ParameterCount actual(argc_); | 3258 ParameterCount actual(argc_); |
| 3267 | 3259 |
| 3260 if (CallAsMethod()) { |
| 3261 if (NeedsChecks()) { |
| 3262 // Do not transform the receiver for strict mode functions and natives. |
| 3263 __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 3264 __ lw(t0, FieldMemOperand(a3, SharedFunctionInfo::kCompilerHintsOffset)); |
| 3265 int32_t strict_mode_function_mask = |
| 3266 1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize); |
| 3267 int32_t native_mask = 1 << (SharedFunctionInfo::kNative + kSmiTagSize); |
| 3268 __ And(at, t0, Operand(strict_mode_function_mask | native_mask)); |
| 3269 __ Branch(&cont, ne, at, Operand(zero_reg)); |
| 3270 } |
| 3271 |
| 3272 // Compute the receiver in non-strict mode. |
| 3273 __ lw(a3, MemOperand(sp, argc_ * kPointerSize)); |
| 3274 |
| 3275 if (NeedsChecks()) { |
| 3276 __ JumpIfSmi(a3, &wrap); |
| 3277 __ GetObjectType(a3, t0, t0); |
| 3278 __ Branch(&wrap, lt, t0, 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, a3); |
| 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 21 matching lines...) Expand all Loading... |
| 5245 // Grab that for the second argument to the hook. | 5260 // Grab that for the second argument to the hook. |
| 5246 __ Addu(a1, sp, Operand(kNumSavedRegs * kPointerSize)); | 5261 __ Addu(a1, sp, Operand(kNumSavedRegs * kPointerSize)); |
| 5247 | 5262 |
| 5248 // Align the stack if necessary. | 5263 // Align the stack if necessary. |
| 5249 int frame_alignment = masm->ActivationFrameAlignment(); | 5264 int frame_alignment = masm->ActivationFrameAlignment(); |
| 5250 if (frame_alignment > kPointerSize) { | 5265 if (frame_alignment > kPointerSize) { |
| 5251 __ mov(s5, sp); | 5266 __ mov(s5, sp); |
| 5252 ASSERT(IsPowerOf2(frame_alignment)); | 5267 ASSERT(IsPowerOf2(frame_alignment)); |
| 5253 __ And(sp, sp, Operand(-frame_alignment)); | 5268 __ And(sp, sp, Operand(-frame_alignment)); |
| 5254 } | 5269 } |
| 5255 | 5270 __ Subu(sp, sp, kCArgsSlotsSize); |
| 5256 #if defined(V8_HOST_ARCH_MIPS) | 5271 #if defined(V8_HOST_ARCH_MIPS) |
| 5257 int32_t entry_hook = | 5272 int32_t entry_hook = |
| 5258 reinterpret_cast<int32_t>(masm->isolate()->function_entry_hook()); | 5273 reinterpret_cast<int32_t>(masm->isolate()->function_entry_hook()); |
| 5259 __ li(at, Operand(entry_hook)); | 5274 __ li(t9, Operand(entry_hook)); |
| 5260 #else | 5275 #else |
| 5261 // Under the simulator we need to indirect the entry hook through a | 5276 // Under the simulator we need to indirect the entry hook through a |
| 5262 // trampoline function at a known address. | 5277 // trampoline function at a known address. |
| 5263 // It additionally takes an isolate as a third parameter. | 5278 // It additionally takes an isolate as a third parameter. |
| 5264 __ li(a2, Operand(ExternalReference::isolate_address(masm->isolate()))); | 5279 __ li(a2, Operand(ExternalReference::isolate_address(masm->isolate()))); |
| 5265 | 5280 |
| 5266 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); | 5281 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); |
| 5267 __ li(at, Operand(ExternalReference(&dispatcher, | 5282 __ li(t9, Operand(ExternalReference(&dispatcher, |
| 5268 ExternalReference::BUILTIN_CALL, | 5283 ExternalReference::BUILTIN_CALL, |
| 5269 masm->isolate()))); | 5284 masm->isolate()))); |
| 5270 #endif | 5285 #endif |
| 5271 __ Call(at); | 5286 // Call C function through t9 to conform ABI for PIC. |
| 5287 __ Call(t9); |
| 5272 | 5288 |
| 5273 // Restore the stack pointer if needed. | 5289 // Restore the stack pointer if needed. |
| 5274 if (frame_alignment > kPointerSize) { | 5290 if (frame_alignment > kPointerSize) { |
| 5275 __ mov(sp, s5); | 5291 __ mov(sp, s5); |
| 5292 } else { |
| 5293 __ Addu(sp, sp, kCArgsSlotsSize); |
| 5276 } | 5294 } |
| 5277 | 5295 |
| 5278 // Also pop ra to get Ret(0). | 5296 // Also pop ra to get Ret(0). |
| 5279 __ MultiPop(kSavedRegs | ra.bit()); | 5297 __ MultiPop(kSavedRegs | ra.bit()); |
| 5280 __ Ret(); | 5298 __ Ret(); |
| 5281 } | 5299 } |
| 5282 | 5300 |
| 5283 | 5301 |
| 5284 template<class T> | 5302 template<class T> |
| 5285 static void CreateArrayDispatch(MacroAssembler* masm, | 5303 static void CreateArrayDispatch(MacroAssembler* masm, |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5712 MemOperand(fp, 6 * kPointerSize), | 5730 MemOperand(fp, 6 * kPointerSize), |
| 5713 NULL); | 5731 NULL); |
| 5714 } | 5732 } |
| 5715 | 5733 |
| 5716 | 5734 |
| 5717 #undef __ | 5735 #undef __ |
| 5718 | 5736 |
| 5719 } } // namespace v8::internal | 5737 } } // namespace v8::internal |
| 5720 | 5738 |
| 5721 #endif // V8_TARGET_ARCH_MIPS | 5739 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |