| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
| 6 | 6 |
| 7 #include "src/crankshaft/x64/lithium-codegen-x64.h" | 7 #include "src/crankshaft/x64/lithium-codegen-x64.h" |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 2175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2186 if (expected.CanBeUndetectable()) { | 2186 if (expected.CanBeUndetectable()) { |
| 2187 // Undetectable -> false. | 2187 // Undetectable -> false. |
| 2188 __ testb(FieldOperand(map, Map::kBitFieldOffset), | 2188 __ testb(FieldOperand(map, Map::kBitFieldOffset), |
| 2189 Immediate(1 << Map::kIsUndetectable)); | 2189 Immediate(1 << Map::kIsUndetectable)); |
| 2190 __ j(not_zero, instr->FalseLabel(chunk_)); | 2190 __ j(not_zero, instr->FalseLabel(chunk_)); |
| 2191 } | 2191 } |
| 2192 } | 2192 } |
| 2193 | 2193 |
| 2194 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 2194 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
| 2195 // spec object -> true. | 2195 // spec object -> true. |
| 2196 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | 2196 __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE); |
| 2197 __ j(above_equal, instr->TrueLabel(chunk_)); | 2197 __ j(above_equal, instr->TrueLabel(chunk_)); |
| 2198 } | 2198 } |
| 2199 | 2199 |
| 2200 if (expected.Contains(ToBooleanStub::STRING)) { | 2200 if (expected.Contains(ToBooleanStub::STRING)) { |
| 2201 // String value -> false iff empty. | 2201 // String value -> false iff empty. |
| 2202 Label not_string; | 2202 Label not_string; |
| 2203 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 2203 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
| 2204 __ j(above_equal, ¬_string, Label::kNear); | 2204 __ j(above_equal, ¬_string, Label::kNear); |
| 2205 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 2205 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 2206 __ j(not_zero, instr->TrueLabel(chunk_)); | 2206 __ j(not_zero, instr->TrueLabel(chunk_)); |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2550 DCHECK(!input.is(temp2)); | 2550 DCHECK(!input.is(temp2)); |
| 2551 DCHECK(!temp.is(temp2)); | 2551 DCHECK(!temp.is(temp2)); |
| 2552 | 2552 |
| 2553 __ JumpIfSmi(input, is_false); | 2553 __ JumpIfSmi(input, is_false); |
| 2554 | 2554 |
| 2555 if (String::Equals(isolate()->factory()->Function_string(), class_name)) { | 2555 if (String::Equals(isolate()->factory()->Function_string(), class_name)) { |
| 2556 // Assuming the following assertions, we can use the same compares to test | 2556 // Assuming the following assertions, we can use the same compares to test |
| 2557 // for both being a function type and being in the object type range. | 2557 // for both being a function type and being in the object type range. |
| 2558 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); | 2558 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |
| 2559 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == | 2559 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == |
| 2560 FIRST_SPEC_OBJECT_TYPE + 1); | 2560 FIRST_JS_RECEIVER_TYPE + 1); |
| 2561 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == | 2561 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == |
| 2562 LAST_SPEC_OBJECT_TYPE - 1); | 2562 LAST_JS_RECEIVER_TYPE - 1); |
| 2563 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 2563 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 2564 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); | 2564 __ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, temp); |
| 2565 __ j(below, is_false); | 2565 __ j(below, is_false); |
| 2566 __ j(equal, is_true); | 2566 __ j(equal, is_true); |
| 2567 __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE); | 2567 __ CmpInstanceType(temp, LAST_JS_RECEIVER_TYPE); |
| 2568 __ j(equal, is_true); | 2568 __ j(equal, is_true); |
| 2569 } else { | 2569 } else { |
| 2570 // Faster code path to avoid two compares: subtract lower bound from the | 2570 // Faster code path to avoid two compares: subtract lower bound from the |
| 2571 // actual type and do a signed compare with the width of the type range. | 2571 // actual type and do a signed compare with the width of the type range. |
| 2572 __ movp(temp, FieldOperand(input, HeapObject::kMapOffset)); | 2572 __ movp(temp, FieldOperand(input, HeapObject::kMapOffset)); |
| 2573 __ movzxbl(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); | 2573 __ movzxbl(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); |
| 2574 __ subp(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2574 __ subp(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 2575 __ cmpp(temp2, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - | 2575 __ cmpp(temp2, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - |
| 2576 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2576 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 2577 __ j(above, is_false); | 2577 __ j(above, is_false); |
| (...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3253 | 3253 |
| 3254 // Normal function. Replace undefined or null with global receiver. | 3254 // Normal function. Replace undefined or null with global receiver. |
| 3255 __ CompareRoot(receiver, Heap::kNullValueRootIndex); | 3255 __ CompareRoot(receiver, Heap::kNullValueRootIndex); |
| 3256 __ j(equal, &global_object, Label::kNear); | 3256 __ j(equal, &global_object, Label::kNear); |
| 3257 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); | 3257 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); |
| 3258 __ j(equal, &global_object, Label::kNear); | 3258 __ j(equal, &global_object, Label::kNear); |
| 3259 | 3259 |
| 3260 // The receiver should be a JS object. | 3260 // The receiver should be a JS object. |
| 3261 Condition is_smi = __ CheckSmi(receiver); | 3261 Condition is_smi = __ CheckSmi(receiver); |
| 3262 DeoptimizeIf(is_smi, instr, Deoptimizer::kSmi); | 3262 DeoptimizeIf(is_smi, instr, Deoptimizer::kSmi); |
| 3263 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); | 3263 __ CmpObjectType(receiver, FIRST_JS_RECEIVER_TYPE, kScratchRegister); |
| 3264 DeoptimizeIf(below, instr, Deoptimizer::kNotAJavaScriptObject); | 3264 DeoptimizeIf(below, instr, Deoptimizer::kNotAJavaScriptObject); |
| 3265 | 3265 |
| 3266 __ jmp(&receiver_ok, Label::kNear); | 3266 __ jmp(&receiver_ok, Label::kNear); |
| 3267 __ bind(&global_object); | 3267 __ bind(&global_object); |
| 3268 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset)); | 3268 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset)); |
| 3269 __ movp(receiver, ContextOperand(receiver, Context::NATIVE_CONTEXT_INDEX)); | 3269 __ movp(receiver, ContextOperand(receiver, Context::NATIVE_CONTEXT_INDEX)); |
| 3270 __ movp(receiver, ContextOperand(receiver, Context::GLOBAL_PROXY_INDEX)); | 3270 __ movp(receiver, ContextOperand(receiver, Context::GLOBAL_PROXY_INDEX)); |
| 3271 | 3271 |
| 3272 __ bind(&receiver_ok); | 3272 __ bind(&receiver_ok); |
| 3273 } | 3273 } |
| (...skipping 2191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5465 __ movzxbl(input, FieldOperand(input, Map::kBitFieldOffset)); | 5465 __ movzxbl(input, FieldOperand(input, Map::kBitFieldOffset)); |
| 5466 __ andb(input, | 5466 __ andb(input, |
| 5467 Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); | 5467 Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); |
| 5468 __ cmpb(input, Immediate(1 << Map::kIsCallable)); | 5468 __ cmpb(input, Immediate(1 << Map::kIsCallable)); |
| 5469 final_branch_condition = equal; | 5469 final_branch_condition = equal; |
| 5470 | 5470 |
| 5471 } else if (String::Equals(type_name, factory->object_string())) { | 5471 } else if (String::Equals(type_name, factory->object_string())) { |
| 5472 __ JumpIfSmi(input, false_label, false_distance); | 5472 __ JumpIfSmi(input, false_label, false_distance); |
| 5473 __ CompareRoot(input, Heap::kNullValueRootIndex); | 5473 __ CompareRoot(input, Heap::kNullValueRootIndex); |
| 5474 __ j(equal, true_label, true_distance); | 5474 __ j(equal, true_label, true_distance); |
| 5475 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 5475 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 5476 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, input); | 5476 __ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, input); |
| 5477 __ j(below, false_label, false_distance); | 5477 __ j(below, false_label, false_distance); |
| 5478 // Check for callable or undetectable objects => false. | 5478 // Check for callable or undetectable objects => false. |
| 5479 __ testb(FieldOperand(input, Map::kBitFieldOffset), | 5479 __ testb(FieldOperand(input, Map::kBitFieldOffset), |
| 5480 Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); | 5480 Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); |
| 5481 final_branch_condition = zero; | 5481 final_branch_condition = zero; |
| 5482 | 5482 |
| 5483 // clang-format off | 5483 // clang-format off |
| 5484 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \ | 5484 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \ |
| 5485 } else if (String::Equals(type_name, factory->type##_string())) { \ | 5485 } else if (String::Equals(type_name, factory->type##_string())) { \ |
| 5486 __ JumpIfSmi(input, false_label, false_distance); \ | 5486 __ JumpIfSmi(input, false_label, false_distance); \ |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5642 GenerateOsrPrologue(); | 5642 GenerateOsrPrologue(); |
| 5643 } | 5643 } |
| 5644 | 5644 |
| 5645 | 5645 |
| 5646 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5646 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
| 5647 DCHECK(ToRegister(instr->context()).is(rsi)); | 5647 DCHECK(ToRegister(instr->context()).is(rsi)); |
| 5648 | 5648 |
| 5649 Condition cc = masm()->CheckSmi(rax); | 5649 Condition cc = masm()->CheckSmi(rax); |
| 5650 DeoptimizeIf(cc, instr, Deoptimizer::kSmi); | 5650 DeoptimizeIf(cc, instr, Deoptimizer::kSmi); |
| 5651 | 5651 |
| 5652 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 5652 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_JS_RECEIVER_TYPE); |
| 5653 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); | 5653 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); |
| 5654 DeoptimizeIf(below_equal, instr, Deoptimizer::kWrongInstanceType); | 5654 DeoptimizeIf(below_equal, instr, Deoptimizer::kWrongInstanceType); |
| 5655 | 5655 |
| 5656 Label use_cache, call_runtime; | 5656 Label use_cache, call_runtime; |
| 5657 Register null_value = rdi; | 5657 Register null_value = rdi; |
| 5658 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 5658 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
| 5659 __ CheckEnumCache(null_value, &call_runtime); | 5659 __ CheckEnumCache(null_value, &call_runtime); |
| 5660 | 5660 |
| 5661 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); | 5661 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); |
| 5662 __ jmp(&use_cache, Label::kNear); | 5662 __ jmp(&use_cache, Label::kNear); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5788 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5788 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 5789 } | 5789 } |
| 5790 | 5790 |
| 5791 | 5791 |
| 5792 #undef __ | 5792 #undef __ |
| 5793 | 5793 |
| 5794 } // namespace internal | 5794 } // namespace internal |
| 5795 } // namespace v8 | 5795 } // namespace v8 |
| 5796 | 5796 |
| 5797 #endif // V8_TARGET_ARCH_X64 | 5797 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |