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 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
8 | 8 |
9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
(...skipping 2353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2364 __ push(edi); | 2364 __ push(edi); |
2365 __ push(eax); | 2365 __ push(eax); |
2366 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 2366 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
2367 __ pop(edi); | 2367 __ pop(edi); |
2368 } | 2368 } |
2369 __ mov(Operand(esp, (argc + 1) * kPointerSize), eax); | 2369 __ mov(Operand(esp, (argc + 1) * kPointerSize), eax); |
2370 __ jmp(cont); | 2370 __ jmp(cont); |
2371 } | 2371 } |
2372 | 2372 |
2373 | 2373 |
2374 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2374 static void CallFunctionNoFeedback(MacroAssembler* masm, |
2375 int argc, bool needs_checks, | |
2376 bool call_as_method) { | |
2375 // edi : the function to call | 2377 // edi : the function to call |
2376 Label slow, non_function, wrap, cont; | 2378 Label slow, non_function, wrap, cont; |
2377 | 2379 |
2378 if (NeedsChecks()) { | 2380 if (needs_checks) { |
2379 // Check that the function really is a JavaScript function. | 2381 // Check that the function really is a JavaScript function. |
2380 __ JumpIfSmi(edi, &non_function); | 2382 __ JumpIfSmi(edi, &non_function); |
2381 | 2383 |
2382 // Goto slow case if we do not have a function. | 2384 // Goto slow case if we do not have a function. |
2383 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2385 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
2384 __ j(not_equal, &slow); | 2386 __ j(not_equal, &slow); |
2385 } | 2387 } |
2386 | 2388 |
2387 // Fast-case: Just invoke the function. | 2389 // Fast-case: Just invoke the function. |
2388 ParameterCount actual(argc_); | 2390 ParameterCount actual(argc); |
2389 | 2391 |
2390 if (CallAsMethod()) { | 2392 if (call_as_method) { |
2391 if (NeedsChecks()) { | 2393 if (needs_checks) { |
2392 EmitContinueIfStrictOrNative(masm, &cont); | 2394 EmitContinueIfStrictOrNative(masm, &cont); |
2393 } | 2395 } |
2394 | 2396 |
2395 // Load the receiver from the stack. | 2397 // Load the receiver from the stack. |
2396 __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize)); | 2398 __ mov(eax, Operand(esp, (argc + 1) * kPointerSize)); |
2397 | 2399 |
2398 if (NeedsChecks()) { | 2400 if (call_as_method) { |
2399 __ JumpIfSmi(eax, &wrap); | 2401 __ JumpIfSmi(eax, &wrap); |
2400 | 2402 |
2401 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | 2403 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); |
2402 __ j(below, &wrap); | 2404 __ j(below, &wrap); |
2403 } else { | 2405 } else { |
2404 __ jmp(&wrap); | 2406 __ jmp(&wrap); |
2405 } | 2407 } |
2406 | 2408 |
2407 __ bind(&cont); | 2409 __ bind(&cont); |
2408 } | 2410 } |
2409 | 2411 |
2410 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); | 2412 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); |
2411 | 2413 |
2412 if (NeedsChecks()) { | 2414 if (needs_checks) { |
2413 // Slow-case: Non-function called. | 2415 // Slow-case: Non-function called. |
2414 __ bind(&slow); | 2416 __ bind(&slow); |
2415 // (non_function is bound in EmitSlowCase) | 2417 // (non_function is bound in EmitSlowCase) |
2416 EmitSlowCase(isolate(), masm, argc_, &non_function); | 2418 EmitSlowCase(masm->isolate(), masm, argc, &non_function); |
2417 } | 2419 } |
2418 | 2420 |
2419 if (CallAsMethod()) { | 2421 if (call_as_method) { |
2420 __ bind(&wrap); | 2422 __ bind(&wrap); |
2421 EmitWrapCase(masm, argc_, &cont); | 2423 EmitWrapCase(masm, argc, &cont); |
2422 } | 2424 } |
2423 } | 2425 } |
2424 | 2426 |
2425 | 2427 |
2428 void CallFunctionStub::Generate(MacroAssembler* masm) { | |
2429 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); | |
2430 } | |
2431 | |
2432 | |
2426 void CallConstructStub::Generate(MacroAssembler* masm) { | 2433 void CallConstructStub::Generate(MacroAssembler* masm) { |
2427 // eax : number of arguments | 2434 // eax : number of arguments |
2428 // ebx : feedback vector | 2435 // ebx : feedback vector |
2429 // edx : (only if ebx is not the megamorphic symbol) slot in feedback | 2436 // edx : (only if ebx is not the megamorphic symbol) slot in feedback |
2430 // vector (Smi) | 2437 // vector (Smi) |
2431 // edi : constructor function | 2438 // edi : constructor function |
2432 Label slow, non_function_call; | 2439 Label slow, non_function_call; |
2433 | 2440 |
2434 // Check that function is not a smi. | 2441 // Check that function is not a smi. |
2435 __ JumpIfSmi(edi, &non_function_call); | 2442 __ JumpIfSmi(edi, &non_function_call); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2492 | 2499 |
2493 | 2500 |
2494 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { | 2501 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { |
2495 __ mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 2502 __ mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
2496 __ mov(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset)); | 2503 __ mov(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset)); |
2497 __ mov(vector, FieldOperand(vector, | 2504 __ mov(vector, FieldOperand(vector, |
2498 SharedFunctionInfo::kFeedbackVectorOffset)); | 2505 SharedFunctionInfo::kFeedbackVectorOffset)); |
2499 } | 2506 } |
2500 | 2507 |
2501 | 2508 |
2509 void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) { | |
2510 // edi - function | |
2511 // ebx - feedback vector | |
2512 // edx - slot id | |
2513 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); | |
2514 __ cmp(edi, ecx); | |
2515 __ j(not_equal, miss); | |
2516 | |
2517 __ mov(eax, arg_count()); | |
2518 __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, | |
2519 FixedArray::kHeaderSize)); | |
2520 // Verify that ecx contains an AllocationSite | |
2521 __ AssertUndefinedOrAllocationSite(ebx); | |
2522 ArrayConstructorStub stub(masm->isolate(), arg_count()); | |
2523 __ TailCallStub(&stub); | |
2524 } | |
2525 | |
2526 | |
2527 void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) { | |
2528 // edi - function | |
2529 // ebx - feedback vector | |
2530 // edx - slot id | |
2531 Label miss; | |
2532 | |
2533 if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) { | |
2534 Generate_MonomorphicArray(masm, &miss); | |
2535 } else { | |
2536 // So far there is only one customer for our custom feedback scheme. | |
2537 UNREACHABLE(); | |
2538 } | |
2539 | |
2540 __ bind(&miss); | |
2541 GenerateMiss(masm); | |
2542 | |
2543 // The slow case, we need this no matter what to complete a call after a miss. | |
2544 CallFunctionNoFeedback(masm, | |
2545 arg_count(), | |
2546 true, | |
2547 CallAsMethod()); | |
2548 | |
2549 // Unreachable. | |
2550 __ int3(); | |
danno
2014/05/16 16:34:11
I think there might be a macro for this.
mvstanton
2014/05/19 13:45:24
There isn't, code even in the macro assembler uses
| |
2551 } | |
2552 | |
2553 | |
2502 void CallICStub::Generate(MacroAssembler* masm) { | 2554 void CallICStub::Generate(MacroAssembler* masm) { |
2503 // edi - function | 2555 // edi - function |
2504 // edx - slot id | 2556 // edx - slot id |
2505 Isolate* isolate = masm->isolate(); | 2557 Isolate* isolate = masm->isolate(); |
2506 Label extra_checks_or_miss, slow_start; | 2558 Label extra_checks_or_miss, slow_start; |
2507 Label slow, non_function, wrap, cont; | 2559 Label slow, non_function, wrap, cont; |
2508 Label have_js_function; | 2560 Label have_js_function; |
2509 int argc = state_.arg_count(); | 2561 int argc = state_.arg_count(); |
2510 ParameterCount actual(argc); | 2562 ParameterCount actual(argc); |
2511 | 2563 |
2512 EmitLoadTypeFeedbackVector(masm, ebx); | 2564 EmitLoadTypeFeedbackVector(masm, ebx); |
2513 | 2565 |
2566 // the MONOMORPHIC_ARRAY case is handled with a helper function. | |
2567 if (state_.stub_type() != CallIC::DEFAULT) { | |
2568 Generate_CustomFeedbackCall(masm); | |
2569 return; | |
2570 } | |
2571 | |
2572 // the MONOMORPHIC_ARRAY case is handled with a helper function. | |
2514 // The checks. First, does edi match the recorded monomorphic target? | 2573 // The checks. First, does edi match the recorded monomorphic target? |
2515 __ cmp(edi, FieldOperand(ebx, edx, times_half_pointer_size, | 2574 __ cmp(edi, FieldOperand(ebx, edx, times_half_pointer_size, |
2516 FixedArray::kHeaderSize)); | 2575 FixedArray::kHeaderSize)); |
2517 __ j(not_equal, &extra_checks_or_miss); | 2576 __ j(not_equal, &extra_checks_or_miss); |
2518 | 2577 |
2519 __ bind(&have_js_function); | 2578 __ bind(&have_js_function); |
2520 if (state_.CallAsMethod()) { | 2579 if (state_.CallAsMethod()) { |
2521 EmitContinueIfStrictOrNative(masm, &cont); | 2580 EmitContinueIfStrictOrNative(masm, &cont); |
2522 | 2581 |
2523 // Load the receiver from the stack. | 2582 // Load the receiver from the stack. |
(...skipping 2604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5128 Operand(ebp, 7 * kPointerSize), | 5187 Operand(ebp, 7 * kPointerSize), |
5129 NULL); | 5188 NULL); |
5130 } | 5189 } |
5131 | 5190 |
5132 | 5191 |
5133 #undef __ | 5192 #undef __ |
5134 | 5193 |
5135 } } // namespace v8::internal | 5194 } } // namespace v8::internal |
5136 | 5195 |
5137 #endif // V8_TARGET_ARCH_IA32 | 5196 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |