OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1690 __ j(equal, is_object); | 1690 __ j(equal, is_object); |
1691 | 1691 |
1692 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); | 1692 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); |
1693 // Undetectable objects behave like undefined. | 1693 // Undetectable objects behave like undefined. |
1694 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), | 1694 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), |
1695 Immediate(1 << Map::kIsUndetectable)); | 1695 Immediate(1 << Map::kIsUndetectable)); |
1696 __ j(not_zero, is_not_object); | 1696 __ j(not_zero, is_not_object); |
1697 | 1697 |
1698 __ movzxbl(kScratchRegister, | 1698 __ movzxbl(kScratchRegister, |
1699 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); | 1699 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); |
1700 __ cmpb(kScratchRegister, Immediate(FIRST_JS_OBJECT_TYPE)); | 1700 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1701 __ j(below, is_not_object); | 1701 __ j(below, is_not_object); |
1702 __ cmpb(kScratchRegister, Immediate(LAST_JS_OBJECT_TYPE)); | 1702 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1703 return below_equal; | 1703 return below_equal; |
1704 } | 1704 } |
1705 | 1705 |
1706 | 1706 |
1707 void LCodeGen::DoIsObject(LIsObject* instr) { | 1707 void LCodeGen::DoIsObject(LIsObject* instr) { |
1708 Register reg = ToRegister(instr->InputAt(0)); | 1708 Register reg = ToRegister(instr->InputAt(0)); |
1709 Register result = ToRegister(instr->result()); | 1709 Register result = ToRegister(instr->result()); |
1710 Label is_false, is_true, done; | 1710 Label is_false, is_true, done; |
1711 | 1711 |
1712 Condition true_cond = EmitIsObject(reg, &is_false, &is_true); | 1712 Condition true_cond = EmitIsObject(reg, &is_false, &is_true); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1900 | 1900 |
1901 | 1901 |
1902 // Branches to a label or falls through with the answer in the z flag. | 1902 // Branches to a label or falls through with the answer in the z flag. |
1903 // Trashes the temp register and possibly input (if it and temp are aliased). | 1903 // Trashes the temp register and possibly input (if it and temp are aliased). |
1904 void LCodeGen::EmitClassOfTest(Label* is_true, | 1904 void LCodeGen::EmitClassOfTest(Label* is_true, |
1905 Label* is_false, | 1905 Label* is_false, |
1906 Handle<String> class_name, | 1906 Handle<String> class_name, |
1907 Register input, | 1907 Register input, |
1908 Register temp) { | 1908 Register temp) { |
1909 __ JumpIfSmi(input, is_false); | 1909 __ JumpIfSmi(input, is_false); |
1910 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, temp); | 1910 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); |
1911 __ j(below, is_false); | 1911 __ j(below, is_false); |
1912 | 1912 |
1913 // Map is now in temp. | 1913 // Map is now in temp. |
1914 // Functions have class 'Function'. | 1914 // Functions have class 'Function'. |
1915 __ CmpInstanceType(temp, JS_FUNCTION_TYPE); | 1915 __ CmpInstanceType(temp, FIRST_CALLABLE_SPEC_OBJECT_TYPE); |
1916 if (class_name->IsEqualTo(CStrVector("Function"))) { | 1916 if (class_name->IsEqualTo(CStrVector("Function"))) { |
1917 __ j(equal, is_true); | 1917 __ j(above_equal, is_true); |
1918 } else { | 1918 } else { |
1919 __ j(equal, is_false); | 1919 __ j(above_equal, is_false); |
1920 } | 1920 } |
1921 | 1921 |
1922 // Check if the constructor in the map is a function. | 1922 // Check if the constructor in the map is a function. |
1923 __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); | 1923 __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); |
1924 | 1924 |
1925 // As long as JS_FUNCTION_TYPE is the last instance type and it is | 1925 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last type and |
1926 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for | 1926 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after |
1927 // LAST_JS_OBJECT_TYPE. | 1927 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter. |
1928 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 1928 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE); |
1929 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); | 1929 STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE == |
| 1930 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1); |
1930 | 1931 |
1931 // Objects with a non-function constructor have class 'Object'. | 1932 // Objects with a non-function constructor have class 'Object'. |
1932 __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister); | 1933 __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister); |
1933 if (class_name->IsEqualTo(CStrVector("Object"))) { | 1934 if (class_name->IsEqualTo(CStrVector("Object"))) { |
1934 __ j(not_equal, is_true); | 1935 __ j(not_equal, is_true); |
1935 } else { | 1936 } else { |
1936 __ j(not_equal, is_false); | 1937 __ j(not_equal, is_false); |
1937 } | 1938 } |
1938 | 1939 |
1939 // temp now contains the constructor function. Grab the | 1940 // temp now contains the constructor function. Grab the |
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2636 | 2637 |
2637 // Normal function. Replace undefined or null with global receiver. | 2638 // Normal function. Replace undefined or null with global receiver. |
2638 __ CompareRoot(receiver, Heap::kNullValueRootIndex); | 2639 __ CompareRoot(receiver, Heap::kNullValueRootIndex); |
2639 __ j(equal, &global_object, Label::kNear); | 2640 __ j(equal, &global_object, Label::kNear); |
2640 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); | 2641 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); |
2641 __ j(equal, &global_object, Label::kNear); | 2642 __ j(equal, &global_object, Label::kNear); |
2642 | 2643 |
2643 // The receiver should be a JS object. | 2644 // The receiver should be a JS object. |
2644 Condition is_smi = __ CheckSmi(receiver); | 2645 Condition is_smi = __ CheckSmi(receiver); |
2645 DeoptimizeIf(is_smi, instr->environment()); | 2646 DeoptimizeIf(is_smi, instr->environment()); |
2646 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister); | 2647 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); |
2647 DeoptimizeIf(below, instr->environment()); | 2648 DeoptimizeIf(below, instr->environment()); |
2648 __ jmp(&receiver_ok, Label::kNear); | 2649 __ jmp(&receiver_ok, Label::kNear); |
2649 | 2650 |
2650 __ bind(&global_object); | 2651 __ bind(&global_object); |
2651 // TODO(kmillikin): We have a hydrogen value for the global object. See | 2652 // TODO(kmillikin): We have a hydrogen value for the global object. See |
2652 // if it's better to use it than to explicitly fetch it from the context | 2653 // if it's better to use it than to explicitly fetch it from the context |
2653 // here. | 2654 // here. |
2654 __ movq(receiver, ContextOperand(rsi, Context::GLOBAL_INDEX)); | 2655 __ movq(receiver, ContextOperand(rsi, Context::GLOBAL_INDEX)); |
2655 __ movq(receiver, | 2656 __ movq(receiver, |
2656 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); | 2657 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); |
(...skipping 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4133 __ j(equal, true_label); | 4134 __ j(equal, true_label); |
4134 __ JumpIfSmi(input, false_label); | 4135 __ JumpIfSmi(input, false_label); |
4135 // Check for undetectable objects => true. | 4136 // Check for undetectable objects => true. |
4136 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); | 4137 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); |
4137 __ testb(FieldOperand(input, Map::kBitFieldOffset), | 4138 __ testb(FieldOperand(input, Map::kBitFieldOffset), |
4138 Immediate(1 << Map::kIsUndetectable)); | 4139 Immediate(1 << Map::kIsUndetectable)); |
4139 final_branch_condition = not_zero; | 4140 final_branch_condition = not_zero; |
4140 | 4141 |
4141 } else if (type_name->Equals(heap()->function_symbol())) { | 4142 } else if (type_name->Equals(heap()->function_symbol())) { |
4142 __ JumpIfSmi(input, false_label); | 4143 __ JumpIfSmi(input, false_label); |
4143 __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input); | 4144 __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input); |
4144 final_branch_condition = above_equal; | 4145 final_branch_condition = above_equal; |
4145 | 4146 |
4146 } else if (type_name->Equals(heap()->object_symbol())) { | 4147 } else if (type_name->Equals(heap()->object_symbol())) { |
4147 __ JumpIfSmi(input, false_label); | 4148 __ JumpIfSmi(input, false_label); |
4148 __ CompareRoot(input, Heap::kNullValueRootIndex); | 4149 __ CompareRoot(input, Heap::kNullValueRootIndex); |
4149 __ j(equal, true_label); | 4150 __ j(equal, true_label); |
4150 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input); | 4151 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); |
4151 __ j(below, false_label); | 4152 __ j(below, false_label); |
4152 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE); | 4153 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
4153 __ j(above_equal, false_label); | 4154 __ j(above, false_label); |
4154 // Check for undetectable objects => false. | 4155 // Check for undetectable objects => false. |
4155 __ testb(FieldOperand(input, Map::kBitFieldOffset), | 4156 __ testb(FieldOperand(input, Map::kBitFieldOffset), |
4156 Immediate(1 << Map::kIsUndetectable)); | 4157 Immediate(1 << Map::kIsUndetectable)); |
4157 final_branch_condition = zero; | 4158 final_branch_condition = zero; |
4158 | 4159 |
4159 } else { | 4160 } else { |
4160 final_branch_condition = never; | 4161 final_branch_condition = never; |
4161 __ jmp(false_label); | 4162 __ jmp(false_label); |
4162 } | 4163 } |
4163 | 4164 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4290 RegisterEnvironmentForDeoptimization(environment); | 4291 RegisterEnvironmentForDeoptimization(environment); |
4291 ASSERT(osr_pc_offset_ == -1); | 4292 ASSERT(osr_pc_offset_ == -1); |
4292 osr_pc_offset_ = masm()->pc_offset(); | 4293 osr_pc_offset_ = masm()->pc_offset(); |
4293 } | 4294 } |
4294 | 4295 |
4295 #undef __ | 4296 #undef __ |
4296 | 4297 |
4297 } } // namespace v8::internal | 4298 } } // namespace v8::internal |
4298 | 4299 |
4299 #endif // V8_TARGET_ARCH_X64 | 4300 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |