| 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 "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
| 8 | 8 |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 } | 77 } |
| 78 | 78 |
| 79 | 79 |
| 80 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( | 80 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( |
| 81 CodeStubInterfaceDescriptor* descriptor) { | 81 CodeStubInterfaceDescriptor* descriptor) { |
| 82 Register registers[] = { esi, ebx, edx }; | 82 Register registers[] = { esi, ebx, edx }; |
| 83 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); | 83 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 84 } | 84 } |
| 85 | 85 |
| 86 | 86 |
| 87 void InstanceofStub::InitializeInterfaceDescriptor( |
| 88 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { |
| 89 Register registers[] = {esi, left(), right()}; |
| 90 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 91 } |
| 92 |
| 93 |
| 94 void CallFunctionStub::InitializeInterfaceDescriptor( |
| 95 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { |
| 96 Register registers[] = {esi, edi}; |
| 97 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 98 } |
| 99 |
| 100 |
| 101 void CallConstructStub::InitializeInterfaceDescriptor( |
| 102 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { |
| 103 // eax : number of arguments |
| 104 // ebx : feedback vector |
| 105 // edx : (only if ebx is not the megamorphic symbol) slot in feedback |
| 106 // vector (Smi) |
| 107 // edi : constructor function |
| 108 // TODO(turbofan): So far we don't gather type feedback and hence skip the |
| 109 // slot parameter, but ArrayConstructStub needs the vector to be undefined. |
| 110 Register registers[] = {esi, eax, edi, ebx}; |
| 111 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 112 } |
| 113 |
| 114 |
| 87 void RegExpConstructResultStub::InitializeInterfaceDescriptor( | 115 void RegExpConstructResultStub::InitializeInterfaceDescriptor( |
| 88 CodeStubInterfaceDescriptor* descriptor) { | 116 CodeStubInterfaceDescriptor* descriptor) { |
| 89 Register registers[] = { esi, ecx, ebx, eax }; | 117 Register registers[] = { esi, ecx, ebx, eax }; |
| 90 descriptor->Initialize( | 118 descriptor->Initialize( |
| 91 MajorKey(), ARRAY_SIZE(registers), registers, | 119 MajorKey(), ARRAY_SIZE(registers), registers, |
| 92 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry); | 120 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry); |
| 93 } | 121 } |
| 94 | 122 |
| 95 | 123 |
| 96 void TransitionElementsKindStub::InitializeInterfaceDescriptor( | 124 void TransitionElementsKindStub::InitializeInterfaceDescriptor( |
| (...skipping 2342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2439 __ mov(object, Operand(esp, 2 * kPointerSize)); | 2467 __ mov(object, Operand(esp, 2 * kPointerSize)); |
| 2440 __ mov(function, Operand(esp, 1 * kPointerSize)); | 2468 __ mov(function, Operand(esp, 1 * kPointerSize)); |
| 2441 } | 2469 } |
| 2442 | 2470 |
| 2443 // Check that the left hand is a JS object. | 2471 // Check that the left hand is a JS object. |
| 2444 __ JumpIfSmi(object, ¬_js_object); | 2472 __ JumpIfSmi(object, ¬_js_object); |
| 2445 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 2473 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); |
| 2446 | 2474 |
| 2447 // If there is a call site cache don't look in the global cache, but do the | 2475 // If there is a call site cache don't look in the global cache, but do the |
| 2448 // real lookup and update the call site cache. | 2476 // real lookup and update the call site cache. |
| 2449 if (!HasCallSiteInlineCheck()) { | 2477 if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) { |
| 2450 // Look up the function and the map in the instanceof cache. | 2478 // Look up the function and the map in the instanceof cache. |
| 2451 Label miss; | 2479 Label miss; |
| 2452 __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); | 2480 __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); |
| 2453 __ j(not_equal, &miss, Label::kNear); | 2481 __ j(not_equal, &miss, Label::kNear); |
| 2454 __ CompareRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex); | 2482 __ CompareRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex); |
| 2455 __ j(not_equal, &miss, Label::kNear); | 2483 __ j(not_equal, &miss, Label::kNear); |
| 2456 __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex); | 2484 __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex); |
| 2457 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2485 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 2458 __ bind(&miss); | 2486 __ bind(&miss); |
| 2459 } | 2487 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2498 __ cmp(scratch, Immediate(factory->null_value())); | 2526 __ cmp(scratch, Immediate(factory->null_value())); |
| 2499 __ j(equal, &is_not_instance, Label::kNear); | 2527 __ j(equal, &is_not_instance, Label::kNear); |
| 2500 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 2528 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 2501 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); | 2529 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); |
| 2502 __ jmp(&loop); | 2530 __ jmp(&loop); |
| 2503 | 2531 |
| 2504 __ bind(&is_instance); | 2532 __ bind(&is_instance); |
| 2505 if (!HasCallSiteInlineCheck()) { | 2533 if (!HasCallSiteInlineCheck()) { |
| 2506 __ mov(eax, Immediate(0)); | 2534 __ mov(eax, Immediate(0)); |
| 2507 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); | 2535 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); |
| 2536 if (ReturnTrueFalseObject()) { |
| 2537 __ mov(eax, factory->true_value()); |
| 2538 } |
| 2508 } else { | 2539 } else { |
| 2509 // Get return address and delta to inlined map check. | 2540 // Get return address and delta to inlined map check. |
| 2510 __ mov(eax, factory->true_value()); | 2541 __ mov(eax, factory->true_value()); |
| 2511 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 2542 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
| 2512 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 2543 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
| 2513 if (FLAG_debug_code) { | 2544 if (FLAG_debug_code) { |
| 2514 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 2545 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
| 2515 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 2546 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
| 2516 } | 2547 } |
| 2517 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 2548 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
| 2518 if (!ReturnTrueFalseObject()) { | 2549 if (!ReturnTrueFalseObject()) { |
| 2519 __ Move(eax, Immediate(0)); | 2550 __ Move(eax, Immediate(0)); |
| 2520 } | 2551 } |
| 2521 } | 2552 } |
| 2522 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2553 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 2523 | 2554 |
| 2524 __ bind(&is_not_instance); | 2555 __ bind(&is_not_instance); |
| 2525 if (!HasCallSiteInlineCheck()) { | 2556 if (!HasCallSiteInlineCheck()) { |
| 2526 __ mov(eax, Immediate(Smi::FromInt(1))); | 2557 __ mov(eax, Immediate(Smi::FromInt(1))); |
| 2527 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); | 2558 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); |
| 2559 if (ReturnTrueFalseObject()) { |
| 2560 __ mov(eax, factory->false_value()); |
| 2561 } |
| 2528 } else { | 2562 } else { |
| 2529 // Get return address and delta to inlined map check. | 2563 // Get return address and delta to inlined map check. |
| 2530 __ mov(eax, factory->false_value()); | 2564 __ mov(eax, factory->false_value()); |
| 2531 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 2565 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
| 2532 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 2566 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
| 2533 if (FLAG_debug_code) { | 2567 if (FLAG_debug_code) { |
| 2534 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 2568 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
| 2535 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 2569 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
| 2536 } | 2570 } |
| 2537 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 2571 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
| 2538 if (!ReturnTrueFalseObject()) { | 2572 if (!ReturnTrueFalseObject()) { |
| 2539 __ Move(eax, Immediate(Smi::FromInt(1))); | 2573 __ Move(eax, Immediate(Smi::FromInt(1))); |
| 2540 } | 2574 } |
| 2541 } | 2575 } |
| 2542 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2576 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 2543 | 2577 |
| 2544 Label object_not_null, object_not_null_or_smi; | 2578 Label object_not_null, object_not_null_or_smi; |
| 2545 __ bind(¬_js_object); | 2579 __ bind(¬_js_object); |
| 2546 // Before null, smi and string value checks, check that the rhs is a function | 2580 // Before null, smi and string value checks, check that the rhs is a function |
| 2547 // as for a non-function rhs an exception needs to be thrown. | 2581 // as for a non-function rhs an exception needs to be thrown. |
| 2548 __ JumpIfSmi(function, &slow, Label::kNear); | 2582 __ JumpIfSmi(function, &slow, Label::kNear); |
| 2549 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); | 2583 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); |
| 2550 __ j(not_equal, &slow, Label::kNear); | 2584 __ j(not_equal, &slow, Label::kNear); |
| 2551 | 2585 |
| 2552 // Null is not instance of anything. | 2586 // Null is not instance of anything. |
| 2553 __ cmp(object, factory->null_value()); | 2587 __ cmp(object, factory->null_value()); |
| 2554 __ j(not_equal, &object_not_null, Label::kNear); | 2588 __ j(not_equal, &object_not_null, Label::kNear); |
| 2555 __ Move(eax, Immediate(Smi::FromInt(1))); | 2589 if (ReturnTrueFalseObject()) { |
| 2590 __ mov(eax, factory->false_value()); |
| 2591 } else { |
| 2592 __ Move(eax, Immediate(Smi::FromInt(1))); |
| 2593 } |
| 2556 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2594 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 2557 | 2595 |
| 2558 __ bind(&object_not_null); | 2596 __ bind(&object_not_null); |
| 2559 // Smi values is not instance of anything. | 2597 // Smi values is not instance of anything. |
| 2560 __ JumpIfNotSmi(object, &object_not_null_or_smi, Label::kNear); | 2598 __ JumpIfNotSmi(object, &object_not_null_or_smi, Label::kNear); |
| 2561 __ Move(eax, Immediate(Smi::FromInt(1))); | 2599 if (ReturnTrueFalseObject()) { |
| 2600 __ mov(eax, factory->false_value()); |
| 2601 } else { |
| 2602 __ Move(eax, Immediate(Smi::FromInt(1))); |
| 2603 } |
| 2562 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2604 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 2563 | 2605 |
| 2564 __ bind(&object_not_null_or_smi); | 2606 __ bind(&object_not_null_or_smi); |
| 2565 // String values is not instance of anything. | 2607 // String values is not instance of anything. |
| 2566 Condition is_string = masm->IsObjectStringType(object, scratch, scratch); | 2608 Condition is_string = masm->IsObjectStringType(object, scratch, scratch); |
| 2567 __ j(NegateCondition(is_string), &slow, Label::kNear); | 2609 __ j(NegateCondition(is_string), &slow, Label::kNear); |
| 2568 __ Move(eax, Immediate(Smi::FromInt(1))); | 2610 if (ReturnTrueFalseObject()) { |
| 2611 __ mov(eax, factory->false_value()); |
| 2612 } else { |
| 2613 __ Move(eax, Immediate(Smi::FromInt(1))); |
| 2614 } |
| 2569 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2615 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 2570 | 2616 |
| 2571 // Slow-case: Go through the JavaScript implementation. | 2617 // Slow-case: Go through the JavaScript implementation. |
| 2572 __ bind(&slow); | 2618 __ bind(&slow); |
| 2573 if (!ReturnTrueFalseObject()) { | 2619 if (!ReturnTrueFalseObject()) { |
| 2574 // Tail call the builtin which returns 0 or 1. | 2620 // Tail call the builtin which returns 0 or 1. |
| 2575 if (HasArgsInRegisters()) { | 2621 if (HasArgsInRegisters()) { |
| 2576 // Push arguments below return address. | 2622 // Push arguments below return address. |
| 2577 __ pop(scratch); | 2623 __ pop(scratch); |
| 2578 __ push(object); | 2624 __ push(object); |
| (...skipping 2027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4606 Operand(ebp, 7 * kPointerSize), | 4652 Operand(ebp, 7 * kPointerSize), |
| 4607 NULL); | 4653 NULL); |
| 4608 } | 4654 } |
| 4609 | 4655 |
| 4610 | 4656 |
| 4611 #undef __ | 4657 #undef __ |
| 4612 | 4658 |
| 4613 } } // namespace v8::internal | 4659 } } // namespace v8::internal |
| 4614 | 4660 |
| 4615 #endif // V8_TARGET_ARCH_X87 | 4661 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |