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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 void KeyedLoadFieldStub::InitializeInterfaceDescriptor( | 163 void KeyedLoadFieldStub::InitializeInterfaceDescriptor( |
164 Isolate* isolate, | 164 Isolate* isolate, |
165 CodeStubInterfaceDescriptor* descriptor) { | 165 CodeStubInterfaceDescriptor* descriptor) { |
166 static Register registers[] = { edx }; | 166 static Register registers[] = { edx }; |
167 descriptor->register_param_count_ = 1; | 167 descriptor->register_param_count_ = 1; |
168 descriptor->register_params_ = registers; | 168 descriptor->register_params_ = registers; |
169 descriptor->deoptimization_handler_ = NULL; | 169 descriptor->deoptimization_handler_ = NULL; |
170 } | 170 } |
171 | 171 |
172 | 172 |
173 void KeyedArrayCallStub::InitializeInterfaceDescriptor( | |
174 Isolate* isolate, | |
175 CodeStubInterfaceDescriptor* descriptor) { | |
176 static Register registers[] = { ecx }; | |
177 descriptor->register_param_count_ = 1; | |
178 descriptor->register_params_ = registers; | |
179 descriptor->continuation_type_ = TAIL_CALL_CONTINUATION; | |
180 descriptor->handler_arguments_mode_ = PASS_ARGUMENTS; | |
181 descriptor->deoptimization_handler_ = | |
182 FUNCTION_ADDR(KeyedCallIC_MissFromStubFailure); | |
183 } | |
184 | |
185 | |
186 void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( | 173 void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( |
187 Isolate* isolate, | 174 Isolate* isolate, |
188 CodeStubInterfaceDescriptor* descriptor) { | 175 CodeStubInterfaceDescriptor* descriptor) { |
189 static Register registers[] = { edx, ecx, eax }; | 176 static Register registers[] = { edx, ecx, eax }; |
190 descriptor->register_param_count_ = 3; | 177 descriptor->register_param_count_ = 3; |
191 descriptor->register_params_ = registers; | 178 descriptor->register_params_ = registers; |
192 descriptor->deoptimization_handler_ = | 179 descriptor->deoptimization_handler_ = |
193 FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure); | 180 FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure); |
194 } | 181 } |
195 | 182 |
(...skipping 2223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2419 // No need for a write barrier here - cells are rescanned. | 2406 // No need for a write barrier here - cells are rescanned. |
2420 | 2407 |
2421 __ bind(&done); | 2408 __ bind(&done); |
2422 } | 2409 } |
2423 | 2410 |
2424 | 2411 |
2425 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2412 void CallFunctionStub::Generate(MacroAssembler* masm) { |
2426 // ebx : cache cell for call target | 2413 // ebx : cache cell for call target |
2427 // edi : the function to call | 2414 // edi : the function to call |
2428 Isolate* isolate = masm->isolate(); | 2415 Isolate* isolate = masm->isolate(); |
2429 Label slow, non_function; | 2416 Label slow, non_function, wrap, cont; |
2430 | 2417 |
2431 // Check that the function really is a JavaScript function. | 2418 if (NeedsChecks()) { |
2432 __ JumpIfSmi(edi, &non_function); | 2419 // Check that the function really is a JavaScript function. |
| 2420 __ JumpIfSmi(edi, &non_function); |
2433 | 2421 |
2434 // Goto slow case if we do not have a function. | 2422 // Goto slow case if we do not have a function. |
2435 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2423 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
2436 __ j(not_equal, &slow); | 2424 __ j(not_equal, &slow); |
2437 | 2425 |
2438 if (RecordCallTarget()) { | 2426 if (RecordCallTarget()) { |
2439 GenerateRecordCallTarget(masm); | 2427 GenerateRecordCallTarget(masm); |
| 2428 } |
2440 } | 2429 } |
2441 | 2430 |
2442 // Fast-case: Just invoke the function. | 2431 // Fast-case: Just invoke the function. |
2443 ParameterCount actual(argc_); | 2432 ParameterCount actual(argc_); |
2444 | 2433 |
| 2434 if (CallAsMethod()) { |
| 2435 if (NeedsChecks()) { |
| 2436 // Do not transform the receiver for strict mode functions. |
| 2437 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 2438 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), |
| 2439 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
| 2440 __ j(not_equal, &cont); |
| 2441 |
| 2442 // Do not transform the receiver for natives (shared already in ecx). |
| 2443 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), |
| 2444 1 << SharedFunctionInfo::kNativeBitWithinByte); |
| 2445 __ j(not_equal, &cont); |
| 2446 } |
| 2447 |
| 2448 // Load the receiver from the stack. |
| 2449 __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize)); |
| 2450 |
| 2451 if (NeedsChecks()) { |
| 2452 __ JumpIfSmi(eax, &wrap); |
| 2453 |
| 2454 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); |
| 2455 __ j(below, &wrap); |
| 2456 } else { |
| 2457 __ jmp(&wrap); |
| 2458 } |
| 2459 |
| 2460 __ bind(&cont); |
| 2461 } |
| 2462 |
2445 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); | 2463 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); |
2446 | 2464 |
2447 // Slow-case: Non-function called. | 2465 if (NeedsChecks()) { |
2448 __ bind(&slow); | 2466 // Slow-case: Non-function called. |
2449 if (RecordCallTarget()) { | 2467 __ bind(&slow); |
2450 // If there is a call target cache, mark it megamorphic in the | 2468 if (RecordCallTarget()) { |
2451 // non-function case. MegamorphicSentinel is an immortal immovable | 2469 // If there is a call target cache, mark it megamorphic in the |
2452 // object (undefined) so no write barrier is needed. | 2470 // non-function case. MegamorphicSentinel is an immortal immovable |
2453 __ mov(FieldOperand(ebx, Cell::kValueOffset), | 2471 // object (undefined) so no write barrier is needed. |
2454 Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); | 2472 __ mov(FieldOperand(ebx, Cell::kValueOffset), |
2455 } | 2473 Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); |
2456 // Check for function proxy. | 2474 } |
2457 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); | 2475 // Check for function proxy. |
2458 __ j(not_equal, &non_function); | 2476 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); |
2459 __ pop(ecx); | 2477 __ j(not_equal, &non_function); |
2460 __ push(edi); // put proxy as additional argument under return address | 2478 __ pop(ecx); |
2461 __ push(ecx); | 2479 __ push(edi); // put proxy as additional argument under return address |
2462 __ Set(eax, Immediate(argc_ + 1)); | 2480 __ push(ecx); |
2463 __ Set(ebx, Immediate(0)); | 2481 __ Set(eax, Immediate(argc_ + 1)); |
2464 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); | 2482 __ Set(ebx, Immediate(0)); |
2465 { | 2483 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); |
| 2484 { |
| 2485 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); |
| 2486 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
| 2487 } |
| 2488 |
| 2489 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 2490 // of the original receiver from the call site). |
| 2491 __ bind(&non_function); |
| 2492 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); |
| 2493 __ Set(eax, Immediate(argc_)); |
| 2494 __ Set(ebx, Immediate(0)); |
| 2495 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
2466 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); | 2496 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); |
2467 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 2497 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
2468 } | 2498 } |
2469 | 2499 |
2470 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 2500 if (CallAsMethod()) { |
2471 // of the original receiver from the call site). | 2501 __ bind(&wrap); |
2472 __ bind(&non_function); | 2502 // Wrap the receiver and patch it back onto the stack. |
2473 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); | 2503 { FrameScope frame_scope(masm, StackFrame::INTERNAL); |
2474 __ Set(eax, Immediate(argc_)); | 2504 __ push(edi); |
2475 __ Set(ebx, Immediate(0)); | 2505 __ push(eax); |
2476 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); | 2506 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
2477 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); | 2507 __ pop(edi); |
2478 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 2508 } |
| 2509 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), eax); |
| 2510 __ jmp(&cont); |
| 2511 } |
2479 } | 2512 } |
2480 | 2513 |
2481 | 2514 |
2482 void CallConstructStub::Generate(MacroAssembler* masm) { | 2515 void CallConstructStub::Generate(MacroAssembler* masm) { |
2483 // eax : number of arguments | 2516 // eax : number of arguments |
2484 // ebx : cache cell for call target | 2517 // ebx : cache cell for call target |
2485 // edi : constructor function | 2518 // edi : constructor function |
2486 Label slow, non_function_call; | 2519 Label slow, non_function_call; |
2487 | 2520 |
2488 // Check that function is not a smi. | 2521 // Check that function is not a smi. |
(...skipping 2389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4878 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4911 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
4879 __ pop(ecx); | 4912 __ pop(ecx); |
4880 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE | 4913 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE |
4881 ? kPointerSize | 4914 ? kPointerSize |
4882 : 0; | 4915 : 0; |
4883 __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); | 4916 __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); |
4884 __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. | 4917 __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. |
4885 } | 4918 } |
4886 | 4919 |
4887 | 4920 |
4888 void StubFailureTailCallTrampolineStub::Generate(MacroAssembler* masm) { | |
4889 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); | |
4890 __ call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
4891 __ mov(edi, eax); | |
4892 int parameter_count_offset = | |
4893 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | |
4894 __ mov(eax, MemOperand(ebp, parameter_count_offset)); | |
4895 // The parameter count above includes the receiver for the arguments passed to | |
4896 // the deoptimization handler. Subtract the receiver for the parameter count | |
4897 // for the call. | |
4898 __ sub(eax, Immediate(1)); | |
4899 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | |
4900 ParameterCount argument_count(eax); | |
4901 __ InvokeFunction(edi, argument_count, JUMP_FUNCTION, NullCallWrapper()); | |
4902 } | |
4903 | |
4904 | |
4905 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4921 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
4906 if (masm->isolate()->function_entry_hook() != NULL) { | 4922 if (masm->isolate()->function_entry_hook() != NULL) { |
4907 ProfileEntryHookStub stub; | 4923 ProfileEntryHookStub stub; |
4908 masm->CallStub(&stub); | 4924 masm->CallStub(&stub); |
4909 } | 4925 } |
4910 } | 4926 } |
4911 | 4927 |
4912 | 4928 |
4913 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 4929 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { |
4914 // Save volatile registers. | 4930 // Save volatile registers. |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5414 Operand(ebp, 7 * kPointerSize), | 5430 Operand(ebp, 7 * kPointerSize), |
5415 NULL); | 5431 NULL); |
5416 } | 5432 } |
5417 | 5433 |
5418 | 5434 |
5419 #undef __ | 5435 #undef __ |
5420 | 5436 |
5421 } } // namespace v8::internal | 5437 } } // namespace v8::internal |
5422 | 5438 |
5423 #endif // V8_TARGET_ARCH_IA32 | 5439 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |