| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 3244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3255 | 3255 |
| 3256 __ Bind(&done); | 3256 __ Bind(&done); |
| 3257 } | 3257 } |
| 3258 | 3258 |
| 3259 | 3259 |
| 3260 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3260 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3261 ASM_LOCATION("CallFunctionStub::Generate"); | 3261 ASM_LOCATION("CallFunctionStub::Generate"); |
| 3262 // x1 function the function to call | 3262 // x1 function the function to call |
| 3263 // x2 cache_cell cache cell for call target | 3263 // x2 cache_cell cache cell for call target |
| 3264 Register function = x1; | 3264 Register function = x1; |
| 3265 Register cache_cell = x2; |
| 3265 Register type = x4; | 3266 Register type = x4; |
| 3266 Label slow, non_function, wrap, cont; | 3267 Label slow, non_function, wrap, cont; |
| 3267 | 3268 |
| 3268 // TODO(jbramley): x2 is clobbered in a number of cases. Is it ever used? | |
| 3269 | |
| 3270 // TODO(jbramley): This function has a lot of unnamed registers. Name them, | 3269 // TODO(jbramley): This function has a lot of unnamed registers. Name them, |
| 3271 // and tidy things up a bit. | 3270 // and tidy things up a bit. |
| 3272 | 3271 |
| 3273 if (NeedsChecks()) { | 3272 if (NeedsChecks()) { |
| 3274 // Check that the function is really a JavaScript function. | 3273 // Check that the function is really a JavaScript function. |
| 3275 __ JumpIfSmi(function, &non_function); | 3274 __ JumpIfSmi(function, &non_function); |
| 3276 | 3275 |
| 3277 // Goto slow case if we do not have a function. | 3276 // Goto slow case if we do not have a function. |
| 3278 __ JumpIfNotObjectType(function, x10, x10, JS_FUNCTION_TYPE, &slow); | 3277 __ JumpIfNotObjectType(function, x10, x10, JS_FUNCTION_TYPE, &slow); |
| 3279 | 3278 |
| 3280 if (RecordCallTarget()) { | 3279 if (RecordCallTarget()) { |
| 3281 GenerateRecordCallTarget(masm); | 3280 GenerateRecordCallTarget(masm); |
| 3282 } | 3281 } |
| 3283 } | 3282 } |
| 3284 | 3283 |
| 3285 // Fast-case: Invoke the function now. | 3284 // Fast-case: Invoke the function now. |
| 3286 // x1 function pushed function | 3285 // x1 function pushed function |
| 3287 ParameterCount actual(argc_); | 3286 ParameterCount actual(argc_); |
| 3288 | 3287 |
| 3289 if (CallAsMethod()) { | 3288 if (CallAsMethod()) { |
| 3290 if (NeedsChecks()) { | 3289 if (NeedsChecks()) { |
| 3291 // Do not transform the receiver for strict mode functions. | 3290 // Do not transform the receiver for strict mode functions. |
| 3292 __ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); | 3291 __ Ldr(x3, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); |
| 3293 __ Ldr(w3, FieldMemOperand(x2, SharedFunctionInfo::kCompilerHintsOffset)); | 3292 __ Ldr(w4, FieldMemOperand(x3, SharedFunctionInfo::kCompilerHintsOffset)); |
| 3294 __ Tbnz(w3, SharedFunctionInfo::kStrictModeFunction, &cont); | 3293 __ Tbnz(w4, SharedFunctionInfo::kStrictModeFunction, &cont); |
| 3295 | 3294 |
| 3296 // Do not transform the receiver for native (Compilerhints already in x3). | 3295 // Do not transform the receiver for native (Compilerhints already in x3). |
| 3297 __ Tbnz(w3, SharedFunctionInfo::kNative, &cont); | 3296 __ Tbnz(w4, SharedFunctionInfo::kNative, &cont); |
| 3298 } | 3297 } |
| 3299 | 3298 |
| 3300 // Compute the receiver in non-strict mode. | 3299 // Compute the receiver in non-strict mode. |
| 3301 __ Peek(x2, argc_ * kPointerSize); | 3300 __ Peek(x3, argc_ * kPointerSize); |
| 3302 | 3301 |
| 3303 if (NeedsChecks()) { | 3302 if (NeedsChecks()) { |
| 3304 // x0: actual number of arguments | 3303 __ JumpIfSmi(x3, &wrap); |
| 3305 // x1: function | 3304 __ JumpIfObjectType(x3, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt); |
| 3306 // x2: first argument | |
| 3307 __ JumpIfSmi(x2, &wrap); | |
| 3308 __ JumpIfObjectType(x2, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt); | |
| 3309 } else { | 3305 } else { |
| 3310 __ B(&wrap); | 3306 __ B(&wrap); |
| 3311 } | 3307 } |
| 3312 | 3308 |
| 3313 __ Bind(&cont); | 3309 __ Bind(&cont); |
| 3314 } | 3310 } |
| 3315 __ InvokeFunction(function, | 3311 __ InvokeFunction(function, |
| 3316 actual, | 3312 actual, |
| 3317 JUMP_FUNCTION, | 3313 JUMP_FUNCTION, |
| 3318 NullCallWrapper()); | 3314 NullCallWrapper()); |
| 3319 | 3315 |
| 3320 if (NeedsChecks()) { | 3316 if (NeedsChecks()) { |
| 3321 // Slow-case: Non-function called. | 3317 // Slow-case: Non-function called. |
| 3322 __ Bind(&slow); | 3318 __ Bind(&slow); |
| 3323 if (RecordCallTarget()) { | 3319 if (RecordCallTarget()) { |
| 3324 // If there is a call target cache, mark it megamorphic in the | 3320 // If there is a call target cache, mark it megamorphic in the |
| 3325 // non-function case. MegamorphicSentinel is an immortal immovable object | 3321 // non-function case. MegamorphicSentinel is an immortal immovable object |
| 3326 // (undefined) so no write barrier is needed. | 3322 // (undefined) so no write barrier is needed. |
| 3327 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), | 3323 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), |
| 3328 masm->isolate()->heap()->undefined_value()); | 3324 masm->isolate()->heap()->undefined_value()); |
| 3329 __ LoadRoot(x11, Heap::kUndefinedValueRootIndex); | 3325 __ LoadRoot(x11, Heap::kUndefinedValueRootIndex); |
| 3330 __ Str(x11, FieldMemOperand(x2, Cell::kValueOffset)); | 3326 __ Str(x11, FieldMemOperand(cache_cell, Cell::kValueOffset)); |
| 3331 } | 3327 } |
| 3332 // Check for function proxy. | 3328 // Check for function proxy. |
| 3333 // x10 : function type. | 3329 // x10 : function type. |
| 3334 __ CompareAndBranch(type, JS_FUNCTION_PROXY_TYPE, ne, &non_function); | 3330 __ CompareAndBranch(type, JS_FUNCTION_PROXY_TYPE, ne, &non_function); |
| 3335 __ Push(function); // put proxy as additional argument | 3331 __ Push(function); // put proxy as additional argument |
| 3336 __ Mov(x0, argc_ + 1); | 3332 __ Mov(x0, argc_ + 1); |
| 3337 __ Mov(x2, 0); | 3333 __ Mov(x2, 0); |
| 3338 __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY); | 3334 __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY); |
| 3339 { | 3335 { |
| 3340 Handle<Code> adaptor = | 3336 Handle<Code> adaptor = |
| 3341 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 3337 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 3342 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3338 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
| 3343 } | 3339 } |
| 3344 | 3340 |
| 3345 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 3341 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 3346 // of the original receiver from the call site). | 3342 // of the original receiver from the call site). |
| 3347 __ Bind(&non_function); | 3343 __ Bind(&non_function); |
| 3348 __ Poke(function, argc_ * kXRegSizeInBytes); | 3344 __ Poke(function, argc_ * kXRegSizeInBytes); |
| 3349 __ Mov(x0, argc_); // Set up the number of arguments. | 3345 __ Mov(x0, argc_); // Set up the number of arguments. |
| 3350 __ Mov(x2, 0); | 3346 __ Mov(x2, 0); |
| 3351 __ GetBuiltinFunction(function, Builtins::CALL_NON_FUNCTION); | 3347 __ GetBuiltinFunction(function, Builtins::CALL_NON_FUNCTION); |
| 3352 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 3348 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 3353 RelocInfo::CODE_TARGET); | 3349 RelocInfo::CODE_TARGET); |
| 3354 } | 3350 } |
| 3355 | 3351 |
| 3356 if (CallAsMethod()) { | 3352 if (CallAsMethod()) { |
| 3357 __ Bind(&wrap); | 3353 __ Bind(&wrap); |
| 3358 // Wrap the receiver and patch it back onto the stack. | 3354 // Wrap the receiver and patch it back onto the stack. |
| 3359 { FrameScope frame_scope(masm, StackFrame::INTERNAL); | 3355 { FrameScope frame_scope(masm, StackFrame::INTERNAL); |
| 3360 __ Push(x1, x2); | 3356 __ Push(x1, x3); |
| 3361 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 3357 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 3362 __ Pop(x1); | 3358 __ Pop(x1); |
| 3363 } | 3359 } |
| 3364 __ Poke(x0, argc_ * kPointerSize); | 3360 __ Poke(x0, argc_ * kPointerSize); |
| 3365 __ B(&cont); | 3361 __ B(&cont); |
| 3366 } | 3362 } |
| 3367 } | 3363 } |
| 3368 | 3364 |
| 3369 | 3365 |
| 3370 void CallConstructStub::Generate(MacroAssembler* masm) { | 3366 void CallConstructStub::Generate(MacroAssembler* masm) { |
| (...skipping 2313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5684 MemOperand(fp, 6 * kPointerSize), | 5680 MemOperand(fp, 6 * kPointerSize), |
| 5685 NULL); | 5681 NULL); |
| 5686 } | 5682 } |
| 5687 | 5683 |
| 5688 | 5684 |
| 5689 #undef __ | 5685 #undef __ |
| 5690 | 5686 |
| 5691 } } // namespace v8::internal | 5687 } } // namespace v8::internal |
| 5692 | 5688 |
| 5693 #endif // V8_TARGET_ARCH_A64 | 5689 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |