| 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 |