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 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1673 __ cmp(input, isolate()->factory()->null_value()); | 1673 __ cmp(input, isolate()->factory()->null_value()); |
1674 __ j(equal, is_object); | 1674 __ j(equal, is_object); |
1675 | 1675 |
1676 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); | 1676 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); |
1677 // Undetectable objects behave like undefined. | 1677 // Undetectable objects behave like undefined. |
1678 __ movzx_b(temp2, FieldOperand(temp1, Map::kBitFieldOffset)); | 1678 __ movzx_b(temp2, FieldOperand(temp1, Map::kBitFieldOffset)); |
1679 __ test(temp2, Immediate(1 << Map::kIsUndetectable)); | 1679 __ test(temp2, Immediate(1 << Map::kIsUndetectable)); |
1680 __ j(not_zero, is_not_object); | 1680 __ j(not_zero, is_not_object); |
1681 | 1681 |
1682 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); | 1682 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); |
1683 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); | 1683 __ cmp(temp2, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); |
1684 __ j(below, is_not_object); | 1684 __ j(below, is_not_object); |
1685 __ cmp(temp2, LAST_JS_OBJECT_TYPE); | 1685 __ cmp(temp2, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
1686 return below_equal; | 1686 return below_equal; |
1687 } | 1687 } |
1688 | 1688 |
1689 | 1689 |
1690 void LCodeGen::DoIsObject(LIsObject* instr) { | 1690 void LCodeGen::DoIsObject(LIsObject* instr) { |
1691 Register reg = ToRegister(instr->InputAt(0)); | 1691 Register reg = ToRegister(instr->InputAt(0)); |
1692 Register result = ToRegister(instr->result()); | 1692 Register result = ToRegister(instr->result()); |
1693 Register temp = ToRegister(instr->TempAt(0)); | 1693 Register temp = ToRegister(instr->TempAt(0)); |
1694 Label is_false, is_true, done; | 1694 Label is_false, is_true, done; |
1695 | 1695 |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1888 void LCodeGen::EmitClassOfTest(Label* is_true, | 1888 void LCodeGen::EmitClassOfTest(Label* is_true, |
1889 Label* is_false, | 1889 Label* is_false, |
1890 Handle<String>class_name, | 1890 Handle<String>class_name, |
1891 Register input, | 1891 Register input, |
1892 Register temp, | 1892 Register temp, |
1893 Register temp2) { | 1893 Register temp2) { |
1894 ASSERT(!input.is(temp)); | 1894 ASSERT(!input.is(temp)); |
1895 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. | 1895 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. |
1896 __ test(input, Immediate(kSmiTagMask)); | 1896 __ test(input, Immediate(kSmiTagMask)); |
1897 __ j(zero, is_false); | 1897 __ j(zero, is_false); |
1898 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, temp); | 1898 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); |
1899 __ j(below, is_false); | 1899 __ j(below, is_false); |
1900 | 1900 |
1901 // Map is now in temp. | 1901 // Map is now in temp. |
1902 // Functions have class 'Function'. | 1902 // Functions have class 'Function'. |
1903 __ CmpInstanceType(temp, JS_FUNCTION_TYPE); | 1903 __ CmpInstanceType(temp, FIRST_CALLABLE_SPEC_OBJECT_TYPE); |
1904 if (class_name->IsEqualTo(CStrVector("Function"))) { | 1904 if (class_name->IsEqualTo(CStrVector("Function"))) { |
1905 __ j(equal, is_true); | 1905 __ j(above_equal, is_true); |
1906 } else { | 1906 } else { |
1907 __ j(equal, is_false); | 1907 __ j(above_equal, is_false); |
1908 } | 1908 } |
1909 | 1909 |
1910 // Check if the constructor in the map is a function. | 1910 // Check if the constructor in the map is a function. |
1911 __ mov(temp, FieldOperand(temp, Map::kConstructorOffset)); | 1911 __ mov(temp, FieldOperand(temp, Map::kConstructorOffset)); |
1912 | 1912 |
1913 // As long as JS_FUNCTION_TYPE is the last instance type and it is | 1913 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and |
1914 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for | 1914 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after |
1915 // LAST_JS_OBJECT_TYPE. | 1915 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter. |
1916 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 1916 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE); |
1917 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); | 1917 STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE == |
| 1918 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1); |
1918 | 1919 |
1919 // Objects with a non-function constructor have class 'Object'. | 1920 // Objects with a non-function constructor have class 'Object'. |
1920 __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2); | 1921 __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2); |
1921 if (class_name->IsEqualTo(CStrVector("Object"))) { | 1922 if (class_name->IsEqualTo(CStrVector("Object"))) { |
1922 __ j(not_equal, is_true); | 1923 __ j(not_equal, is_true); |
1923 } else { | 1924 } else { |
1924 __ j(not_equal, is_false); | 1925 __ j(not_equal, is_false); |
1925 } | 1926 } |
1926 | 1927 |
1927 // temp now contains the constructor function. Grab the | 1928 // temp now contains the constructor function. Grab the |
(...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2628 | 2629 |
2629 // Normal function. Replace undefined or null with global receiver. | 2630 // Normal function. Replace undefined or null with global receiver. |
2630 __ cmp(receiver, factory()->null_value()); | 2631 __ cmp(receiver, factory()->null_value()); |
2631 __ j(equal, &global_object, Label::kNear); | 2632 __ j(equal, &global_object, Label::kNear); |
2632 __ cmp(receiver, factory()->undefined_value()); | 2633 __ cmp(receiver, factory()->undefined_value()); |
2633 __ j(equal, &global_object, Label::kNear); | 2634 __ j(equal, &global_object, Label::kNear); |
2634 | 2635 |
2635 // The receiver should be a JS object. | 2636 // The receiver should be a JS object. |
2636 __ test(receiver, Immediate(kSmiTagMask)); | 2637 __ test(receiver, Immediate(kSmiTagMask)); |
2637 DeoptimizeIf(equal, instr->environment()); | 2638 DeoptimizeIf(equal, instr->environment()); |
2638 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch); | 2639 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); |
2639 DeoptimizeIf(below, instr->environment()); | 2640 DeoptimizeIf(below, instr->environment()); |
2640 __ jmp(&receiver_ok, Label::kNear); | 2641 __ jmp(&receiver_ok, Label::kNear); |
2641 | 2642 |
2642 __ bind(&global_object); | 2643 __ bind(&global_object); |
2643 // TODO(kmillikin): We have a hydrogen value for the global object. See | 2644 // TODO(kmillikin): We have a hydrogen value for the global object. See |
2644 // if it's better to use it than to explicitly fetch it from the context | 2645 // if it's better to use it than to explicitly fetch it from the context |
2645 // here. | 2646 // here. |
2646 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2647 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2647 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); | 2648 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); |
2648 __ mov(receiver, | 2649 __ mov(receiver, |
(...skipping 1655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4304 __ cmp(input, factory()->undefined_value()); | 4305 __ cmp(input, factory()->undefined_value()); |
4305 __ j(equal, true_label); | 4306 __ j(equal, true_label); |
4306 __ JumpIfSmi(input, false_label); | 4307 __ JumpIfSmi(input, false_label); |
4307 // Check for undetectable objects => true. | 4308 // Check for undetectable objects => true. |
4308 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); | 4309 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); |
4309 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 4310 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
4310 1 << Map::kIsUndetectable); | 4311 1 << Map::kIsUndetectable); |
4311 final_branch_condition = not_zero; | 4312 final_branch_condition = not_zero; |
4312 | 4313 |
4313 } else if (type_name->Equals(heap()->function_symbol())) { | 4314 } else if (type_name->Equals(heap()->function_symbol())) { |
| 4315 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE); |
4314 __ JumpIfSmi(input, false_label); | 4316 __ JumpIfSmi(input, false_label); |
4315 __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input); | 4317 __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input); |
4316 final_branch_condition = above_equal; | 4318 final_branch_condition = above_equal; |
4317 | 4319 |
4318 } else if (type_name->Equals(heap()->object_symbol())) { | 4320 } else if (type_name->Equals(heap()->object_symbol())) { |
4319 __ JumpIfSmi(input, false_label); | 4321 __ JumpIfSmi(input, false_label); |
4320 __ cmp(input, factory()->null_value()); | 4322 __ cmp(input, factory()->null_value()); |
4321 __ j(equal, true_label); | 4323 __ j(equal, true_label); |
4322 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input); | 4324 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); |
4323 __ j(below, false_label); | 4325 __ j(below, false_label); |
4324 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE); | 4326 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
4325 __ j(above_equal, false_label); | 4327 __ j(above, false_label); |
4326 // Check for undetectable objects => false. | 4328 // Check for undetectable objects => false. |
4327 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 4329 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
4328 1 << Map::kIsUndetectable); | 4330 1 << Map::kIsUndetectable); |
4329 final_branch_condition = zero; | 4331 final_branch_condition = zero; |
4330 | 4332 |
4331 } else { | 4333 } else { |
4332 final_branch_condition = not_equal; | 4334 final_branch_condition = not_equal; |
4333 __ jmp(false_label); | 4335 __ jmp(false_label); |
4334 // A dead branch instruction will be generated after this point. | 4336 // A dead branch instruction will be generated after this point. |
4335 } | 4337 } |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4479 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4481 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
4480 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4482 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
4481 } | 4483 } |
4482 | 4484 |
4483 | 4485 |
4484 #undef __ | 4486 #undef __ |
4485 | 4487 |
4486 } } // namespace v8::internal | 4488 } } // namespace v8::internal |
4487 | 4489 |
4488 #endif // V8_TARGET_ARCH_IA32 | 4490 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |