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 1658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1669 __ j(equal, is_object); | 1669 __ j(equal, is_object); |
1670 | 1670 |
1671 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); | 1671 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); |
1672 // Undetectable objects behave like undefined. | 1672 // Undetectable objects behave like undefined. |
1673 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), | 1673 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), |
1674 Immediate(1 << Map::kIsUndetectable)); | 1674 Immediate(1 << Map::kIsUndetectable)); |
1675 __ j(not_zero, is_not_object); | 1675 __ j(not_zero, is_not_object); |
1676 | 1676 |
1677 __ movzxbl(kScratchRegister, | 1677 __ movzxbl(kScratchRegister, |
1678 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); | 1678 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); |
1679 __ cmpb(kScratchRegister, Immediate(FIRST_JS_OBJECT_TYPE)); | 1679 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1680 __ j(below, is_not_object); | 1680 __ j(below, is_not_object); |
1681 __ cmpb(kScratchRegister, Immediate(LAST_JS_OBJECT_TYPE)); | 1681 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1682 return below_equal; | 1682 return below_equal; |
1683 } | 1683 } |
1684 | 1684 |
1685 | 1685 |
1686 void LCodeGen::DoIsObject(LIsObject* instr) { | 1686 void LCodeGen::DoIsObject(LIsObject* instr) { |
1687 Register reg = ToRegister(instr->InputAt(0)); | 1687 Register reg = ToRegister(instr->InputAt(0)); |
1688 Register result = ToRegister(instr->result()); | 1688 Register result = ToRegister(instr->result()); |
1689 Label is_false, is_true, done; | 1689 Label is_false, is_true, done; |
1690 | 1690 |
1691 Condition true_cond = EmitIsObject(reg, &is_false, &is_true); | 1691 Condition true_cond = EmitIsObject(reg, &is_false, &is_true); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1879 | 1879 |
1880 | 1880 |
1881 // Branches to a label or falls through with the answer in the z flag. | 1881 // Branches to a label or falls through with the answer in the z flag. |
1882 // Trashes the temp register and possibly input (if it and temp are aliased). | 1882 // Trashes the temp register and possibly input (if it and temp are aliased). |
1883 void LCodeGen::EmitClassOfTest(Label* is_true, | 1883 void LCodeGen::EmitClassOfTest(Label* is_true, |
1884 Label* is_false, | 1884 Label* is_false, |
1885 Handle<String> class_name, | 1885 Handle<String> class_name, |
1886 Register input, | 1886 Register input, |
1887 Register temp) { | 1887 Register temp) { |
1888 __ JumpIfSmi(input, is_false); | 1888 __ JumpIfSmi(input, is_false); |
1889 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, temp); | 1889 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); |
1890 __ j(below, is_false); | 1890 __ j(below, is_false); |
1891 | 1891 |
1892 // Map is now in temp. | 1892 // Map is now in temp. |
1893 // Functions have class 'Function'. | 1893 // Functions have class 'Function'. |
1894 __ CmpInstanceType(temp, JS_FUNCTION_TYPE); | 1894 __ CmpInstanceType(temp, FIRST_CALLABLE_SPEC_OBJECT_TYPE); |
1895 if (class_name->IsEqualTo(CStrVector("Function"))) { | 1895 if (class_name->IsEqualTo(CStrVector("Function"))) { |
1896 __ j(equal, is_true); | 1896 __ j(greater_equal, is_true); |
Kevin Millikin (Chromium)
2011/05/30 16:32:29
Here: above_equal, and also just below.
rossberg
2011/05/31 14:50:24
Done.
| |
1897 } else { | 1897 } else { |
1898 __ j(equal, is_false); | 1898 __ j(greater_equal, is_false); |
1899 } | 1899 } |
1900 | 1900 |
1901 // Check if the constructor in the map is a function. | 1901 // Check if the constructor in the map is a function. |
1902 __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); | 1902 __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); |
1903 | 1903 |
1904 // As long as JS_FUNCTION_TYPE is the last instance type and it is | 1904 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last type and |
1905 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for | 1905 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after |
1906 // LAST_JS_OBJECT_TYPE. | 1906 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter. |
1907 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 1907 ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE); |
1908 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); | 1908 ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE == |
1909 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1); | |
1909 | 1910 |
1910 // Objects with a non-function constructor have class 'Object'. | 1911 // Objects with a non-function constructor have class 'Object'. |
1911 __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister); | 1912 __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister); |
1912 if (class_name->IsEqualTo(CStrVector("Object"))) { | 1913 if (class_name->IsEqualTo(CStrVector("Object"))) { |
1913 __ j(not_equal, is_true); | 1914 __ j(not_equal, is_true); |
1914 } else { | 1915 } else { |
1915 __ j(not_equal, is_false); | 1916 __ j(not_equal, is_false); |
1916 } | 1917 } |
1917 | 1918 |
1918 // temp now contains the constructor function. Grab the | 1919 // temp now contains the constructor function. Grab the |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2597 // as a receiver. | 2598 // as a receiver. |
2598 Label global_object, receiver_ok; | 2599 Label global_object, receiver_ok; |
2599 __ CompareRoot(receiver, Heap::kNullValueRootIndex); | 2600 __ CompareRoot(receiver, Heap::kNullValueRootIndex); |
2600 __ j(equal, &global_object, Label::kNear); | 2601 __ j(equal, &global_object, Label::kNear); |
2601 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); | 2602 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); |
2602 __ j(equal, &global_object, Label::kNear); | 2603 __ j(equal, &global_object, Label::kNear); |
2603 | 2604 |
2604 // The receiver should be a JS object. | 2605 // The receiver should be a JS object. |
2605 Condition is_smi = __ CheckSmi(receiver); | 2606 Condition is_smi = __ CheckSmi(receiver); |
2606 DeoptimizeIf(is_smi, instr->environment()); | 2607 DeoptimizeIf(is_smi, instr->environment()); |
2607 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister); | 2608 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); |
2608 DeoptimizeIf(below, instr->environment()); | 2609 DeoptimizeIf(below, instr->environment()); |
2609 __ jmp(&receiver_ok, Label::kNear); | 2610 __ jmp(&receiver_ok, Label::kNear); |
2610 | 2611 |
2611 __ bind(&global_object); | 2612 __ bind(&global_object); |
2612 // TODO(kmillikin): We have a hydrogen value for the global object. See | 2613 // TODO(kmillikin): We have a hydrogen value for the global object. See |
2613 // if it's better to use it than to explicitly fetch it from the context | 2614 // if it's better to use it than to explicitly fetch it from the context |
2614 // here. | 2615 // here. |
2615 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2616 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2616 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); | 2617 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); |
2617 __ bind(&receiver_ok); | 2618 __ bind(&receiver_ok); |
(...skipping 1461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4079 __ j(equal, true_label); | 4080 __ j(equal, true_label); |
4080 __ JumpIfSmi(input, false_label); | 4081 __ JumpIfSmi(input, false_label); |
4081 // Check for undetectable objects => true. | 4082 // Check for undetectable objects => true. |
4082 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); | 4083 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); |
4083 __ testb(FieldOperand(input, Map::kBitFieldOffset), | 4084 __ testb(FieldOperand(input, Map::kBitFieldOffset), |
4084 Immediate(1 << Map::kIsUndetectable)); | 4085 Immediate(1 << Map::kIsUndetectable)); |
4085 final_branch_condition = not_zero; | 4086 final_branch_condition = not_zero; |
4086 | 4087 |
4087 } else if (type_name->Equals(heap()->function_symbol())) { | 4088 } else if (type_name->Equals(heap()->function_symbol())) { |
4088 __ JumpIfSmi(input, false_label); | 4089 __ JumpIfSmi(input, false_label); |
4089 __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input); | 4090 __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input); |
4090 final_branch_condition = above_equal; | 4091 final_branch_condition = above_equal; |
4091 | 4092 |
4092 } else if (type_name->Equals(heap()->object_symbol())) { | 4093 } else if (type_name->Equals(heap()->object_symbol())) { |
4093 __ JumpIfSmi(input, false_label); | 4094 __ JumpIfSmi(input, false_label); |
4094 __ CompareRoot(input, Heap::kNullValueRootIndex); | 4095 __ CompareRoot(input, Heap::kNullValueRootIndex); |
4095 __ j(equal, true_label); | 4096 __ j(equal, true_label); |
4096 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input); | 4097 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); |
4097 __ j(below, false_label); | 4098 __ j(below, false_label); |
4098 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE); | 4099 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
4099 __ j(above_equal, false_label); | 4100 __ j(above, false_label); |
4100 // Check for undetectable objects => false. | 4101 // Check for undetectable objects => false. |
4101 __ testb(FieldOperand(input, Map::kBitFieldOffset), | 4102 __ testb(FieldOperand(input, Map::kBitFieldOffset), |
4102 Immediate(1 << Map::kIsUndetectable)); | 4103 Immediate(1 << Map::kIsUndetectable)); |
4103 final_branch_condition = zero; | 4104 final_branch_condition = zero; |
4104 | 4105 |
4105 } else { | 4106 } else { |
4106 final_branch_condition = never; | 4107 final_branch_condition = never; |
4107 __ jmp(false_label); | 4108 __ jmp(false_label); |
4108 } | 4109 } |
4109 | 4110 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4236 RegisterEnvironmentForDeoptimization(environment); | 4237 RegisterEnvironmentForDeoptimization(environment); |
4237 ASSERT(osr_pc_offset_ == -1); | 4238 ASSERT(osr_pc_offset_ == -1); |
4238 osr_pc_offset_ = masm()->pc_offset(); | 4239 osr_pc_offset_ = masm()->pc_offset(); |
4239 } | 4240 } |
4240 | 4241 |
4241 #undef __ | 4242 #undef __ |
4242 | 4243 |
4243 } } // namespace v8::internal | 4244 } } // namespace v8::internal |
4244 | 4245 |
4245 #endif // V8_TARGET_ARCH_X64 | 4246 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |