 Chromium Code Reviews
 Chromium Code Reviews Issue 279423005:
  Customized support for feedback on calls to Array.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 279423005:
  Customized support for feedback on calls to Array.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| 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 |