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