Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 142813003: A64: Synchronize with r15358. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/frames-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 1509 matching lines...) Expand 10 before | Expand all | Expand 10 after
1520 case Token::BIT_XOR: 1520 case Token::BIT_XOR:
1521 case Token::SAR: 1521 case Token::SAR:
1522 case Token::SHL: 1522 case Token::SHL:
1523 case Token::SHR: 1523 case Token::SHR:
1524 GenerateRegisterArgsPush(masm); 1524 GenerateRegisterArgsPush(masm);
1525 break; 1525 break;
1526 default: 1526 default:
1527 UNREACHABLE(); 1527 UNREACHABLE();
1528 } 1528 }
1529 1529
1530 if (op_ == Token::MOD && has_fixed_right_arg_) { 1530 if (op_ == Token::MOD && encoded_right_arg_.has_value) {
1531 // It is guaranteed that the value will fit into a Smi, because if it 1531 // It is guaranteed that the value will fit into a Smi, because if it
1532 // didn't, we wouldn't be here, see BinaryOp_Patch. 1532 // didn't, we wouldn't be here, see BinaryOp_Patch.
1533 __ cmp(eax, Immediate(Smi::FromInt(fixed_right_arg_value()))); 1533 __ cmp(eax, Immediate(Smi::FromInt(fixed_right_arg_value())));
1534 __ j(not_equal, &right_arg_changed); 1534 __ j(not_equal, &right_arg_changed);
1535 } 1535 }
1536 1536
1537 if (result_type_ == BinaryOpIC::UNINITIALIZED || 1537 if (result_type_ == BinaryOpIC::UNINITIALIZED ||
1538 result_type_ == BinaryOpIC::SMI) { 1538 result_type_ == BinaryOpIC::SMI) {
1539 BinaryOpStub_GenerateSmiCode( 1539 BinaryOpStub_GenerateSmiCode(
1540 masm, &call_runtime, NO_HEAPNUMBER_RESULTS, op_); 1540 masm, &call_runtime, NO_HEAPNUMBER_RESULTS, op_);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1662 } 1662 }
1663 if (right_type_ == BinaryOpIC::SMI) { 1663 if (right_type_ == BinaryOpIC::SMI) {
1664 __ JumpIfNotSmi(eax, &not_int32); 1664 __ JumpIfNotSmi(eax, &not_int32);
1665 } 1665 }
1666 FloatingPointHelper::LoadSSE2Operands(masm, &not_floats); 1666 FloatingPointHelper::LoadSSE2Operands(masm, &not_floats);
1667 FloatingPointHelper::CheckSSE2OperandIsInt32( 1667 FloatingPointHelper::CheckSSE2OperandIsInt32(
1668 masm, &not_int32, xmm0, ebx, ecx, xmm2); 1668 masm, &not_int32, xmm0, ebx, ecx, xmm2);
1669 FloatingPointHelper::CheckSSE2OperandIsInt32( 1669 FloatingPointHelper::CheckSSE2OperandIsInt32(
1670 masm, &not_int32, xmm1, edi, ecx, xmm2); 1670 masm, &not_int32, xmm1, edi, ecx, xmm2);
1671 if (op_ == Token::MOD) { 1671 if (op_ == Token::MOD) {
1672 if (has_fixed_right_arg_) { 1672 if (encoded_right_arg_.has_value) {
1673 __ cmp(edi, Immediate(fixed_right_arg_value())); 1673 __ cmp(edi, Immediate(fixed_right_arg_value()));
1674 __ j(not_equal, &right_arg_changed); 1674 __ j(not_equal, &right_arg_changed);
1675 } 1675 }
1676 GenerateRegisterArgsPush(masm); 1676 GenerateRegisterArgsPush(masm);
1677 __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); 1677 __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
1678 } else { 1678 } else {
1679 switch (op_) { 1679 switch (op_) {
1680 case Token::ADD: __ addsd(xmm0, xmm1); break; 1680 case Token::ADD: __ addsd(xmm0, xmm1); break;
1681 case Token::SUB: __ subsd(xmm0, xmm1); break; 1681 case Token::SUB: __ subsd(xmm0, xmm1); break;
1682 case Token::MUL: __ mulsd(xmm0, xmm1); break; 1682 case Token::MUL: __ mulsd(xmm0, xmm1); break;
(...skipping 2988 matching lines...) Expand 10 before | Expand all | Expand 10 after
4671 void StackCheckStub::Generate(MacroAssembler* masm) { 4671 void StackCheckStub::Generate(MacroAssembler* masm) {
4672 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); 4672 __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
4673 } 4673 }
4674 4674
4675 4675
4676 void InterruptStub::Generate(MacroAssembler* masm) { 4676 void InterruptStub::Generate(MacroAssembler* masm) {
4677 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); 4677 __ TailCallRuntime(Runtime::kInterrupt, 0, 1);
4678 } 4678 }
4679 4679
4680 4680
4681 static void GenerateRecordCallTargetNoArray(MacroAssembler* masm) {
4682 // Cache the called function in a global property cell. Cache states
4683 // are uninitialized, monomorphic (indicated by a JSFunction), and
4684 // megamorphic.
4685 // ebx : cache cell for call target
4686 // edi : the function to call
4687 Isolate* isolate = masm->isolate();
4688 Label initialize, done;
4689
4690 // Load the cache state into ecx.
4691 __ mov(ecx, FieldOperand(ebx, PropertyCell::kValueOffset));
4692
4693 // A monomorphic cache hit or an already megamorphic state: invoke the
4694 // function without changing the state.
4695 __ cmp(ecx, edi);
4696 __ j(equal, &done, Label::kNear);
4697 __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
4698 __ j(equal, &done, Label::kNear);
4699
4700 // A monomorphic miss (i.e, here the cache is not uninitialized) goes
4701 // megamorphic.
4702 __ cmp(ecx, Immediate(TypeFeedbackCells::UninitializedSentinel(isolate)));
4703 __ j(equal, &initialize, Label::kNear);
4704 // MegamorphicSentinel is an immortal immovable object (undefined) so no
4705 // write-barrier is needed.
4706 __ mov(FieldOperand(ebx, Cell::kValueOffset),
4707 Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
4708 __ jmp(&done, Label::kNear);
4709
4710 // An uninitialized cache is patched with the function.
4711 __ bind(&initialize);
4712 __ mov(FieldOperand(ebx, Cell::kValueOffset), edi);
4713 // No need for a write barrier here - cells are rescanned.
4714
4715 __ bind(&done);
4716 }
4717
4718
4719 static void GenerateRecordCallTarget(MacroAssembler* masm) { 4681 static void GenerateRecordCallTarget(MacroAssembler* masm) {
4720 // Cache the called function in a global property cell. Cache states 4682 // Cache the called function in a global property cell. Cache states
4721 // are uninitialized, monomorphic (indicated by a JSFunction), and 4683 // are uninitialized, monomorphic (indicated by a JSFunction), and
4722 // megamorphic. 4684 // megamorphic.
4723 // ebx : cache cell for call target 4685 // ebx : cache cell for call target
4724 // edi : the function to call 4686 // edi : the function to call
4725 ASSERT(FLAG_optimize_constructed_arrays);
4726 Isolate* isolate = masm->isolate(); 4687 Isolate* isolate = masm->isolate();
4727 Label initialize, done, miss, megamorphic, not_array_function; 4688 Label initialize, done, miss, megamorphic, not_array_function;
4728 4689
4729 // Load the cache state into ecx. 4690 // Load the cache state into ecx.
4730 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset)); 4691 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset));
4731 4692
4732 // A monomorphic cache hit or an already megamorphic state: invoke the 4693 // A monomorphic cache hit or an already megamorphic state: invoke the
4733 // function without changing the state. 4694 // function without changing the state.
4734 __ cmp(ecx, edi); 4695 __ cmp(ecx, edi);
4735 __ j(equal, &done); 4696 __ j(equal, &done);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
4817 __ bind(&receiver_ok); 4778 __ bind(&receiver_ok);
4818 } 4779 }
4819 4780
4820 // Check that the function really is a JavaScript function. 4781 // Check that the function really is a JavaScript function.
4821 __ JumpIfSmi(edi, &non_function); 4782 __ JumpIfSmi(edi, &non_function);
4822 // Goto slow case if we do not have a function. 4783 // Goto slow case if we do not have a function.
4823 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 4784 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
4824 __ j(not_equal, &slow); 4785 __ j(not_equal, &slow);
4825 4786
4826 if (RecordCallTarget()) { 4787 if (RecordCallTarget()) {
4827 if (FLAG_optimize_constructed_arrays) { 4788 GenerateRecordCallTarget(masm);
4828 GenerateRecordCallTarget(masm);
4829 } else {
4830 GenerateRecordCallTargetNoArray(masm);
4831 }
4832 } 4789 }
4833 4790
4834 // Fast-case: Just invoke the function. 4791 // Fast-case: Just invoke the function.
4835 ParameterCount actual(argc_); 4792 ParameterCount actual(argc_);
4836 4793
4837 if (ReceiverMightBeImplicit()) { 4794 if (ReceiverMightBeImplicit()) {
4838 Label call_as_function; 4795 Label call_as_function;
4839 __ cmp(eax, isolate->factory()->the_hole_value()); 4796 __ cmp(eax, isolate->factory()->the_hole_value());
4840 __ j(equal, &call_as_function); 4797 __ j(equal, &call_as_function);
4841 __ InvokeFunction(edi, 4798 __ InvokeFunction(edi,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
4894 // edi : constructor function 4851 // edi : constructor function
4895 Label slow, non_function_call; 4852 Label slow, non_function_call;
4896 4853
4897 // Check that function is not a smi. 4854 // Check that function is not a smi.
4898 __ JumpIfSmi(edi, &non_function_call); 4855 __ JumpIfSmi(edi, &non_function_call);
4899 // Check that function is a JSFunction. 4856 // Check that function is a JSFunction.
4900 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 4857 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
4901 __ j(not_equal, &slow); 4858 __ j(not_equal, &slow);
4902 4859
4903 if (RecordCallTarget()) { 4860 if (RecordCallTarget()) {
4904 if (FLAG_optimize_constructed_arrays) { 4861 GenerateRecordCallTarget(masm);
4905 GenerateRecordCallTarget(masm);
4906 } else {
4907 GenerateRecordCallTargetNoArray(masm);
4908 }
4909 } 4862 }
4910 4863
4911 // Jump to the function-specific construct stub. 4864 // Jump to the function-specific construct stub.
4912 Register jmp_reg = FLAG_optimize_constructed_arrays ? ecx : ebx; 4865 Register jmp_reg = ecx;
4913 __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 4866 __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
4914 __ mov(jmp_reg, FieldOperand(jmp_reg, 4867 __ mov(jmp_reg, FieldOperand(jmp_reg,
4915 SharedFunctionInfo::kConstructStubOffset)); 4868 SharedFunctionInfo::kConstructStubOffset));
4916 __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize)); 4869 __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize));
4917 __ jmp(jmp_reg); 4870 __ jmp(jmp_reg);
4918 4871
4919 // edi: called object 4872 // edi: called object
4920 // eax: number of arguments 4873 // eax: number of arguments
4921 // ecx: object map 4874 // ecx: object map
4922 Label do_call; 4875 Label do_call;
(...skipping 25 matching lines...) Expand all
4948 result_size_ == 1; 4901 result_size_ == 1;
4949 } 4902 }
4950 4903
4951 4904
4952 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 4905 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
4953 CEntryStub::GenerateAheadOfTime(isolate); 4906 CEntryStub::GenerateAheadOfTime(isolate);
4954 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 4907 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
4955 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 4908 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
4956 // It is important that the store buffer overflow stubs are generated first. 4909 // It is important that the store buffer overflow stubs are generated first.
4957 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); 4910 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate);
4958 if (FLAG_optimize_constructed_arrays) { 4911 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
4959 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
4960 }
4961 } 4912 }
4962 4913
4963 4914
4964 void CodeStub::GenerateFPStubs(Isolate* isolate) { 4915 void CodeStub::GenerateFPStubs(Isolate* isolate) {
4965 if (CpuFeatures::IsSupported(SSE2)) { 4916 if (CpuFeatures::IsSupported(SSE2)) {
4966 CEntryStub save_doubles(1, kSaveFPRegs); 4917 CEntryStub save_doubles(1, kSaveFPRegs);
4967 // Stubs might already be in the snapshot, detect that and don't regenerate, 4918 // Stubs might already be in the snapshot, detect that and don't regenerate,
4968 // which would lead to code stub initialization state being messed up. 4919 // which would lead to code stub initialization state being messed up.
4969 Code* save_doubles_code; 4920 Code* save_doubles_code;
4970 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { 4921 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
5043 if (always_allocate_scope) { 4994 if (always_allocate_scope) {
5044 __ dec(Operand::StaticVariable(scope_depth)); 4995 __ dec(Operand::StaticVariable(scope_depth));
5045 } 4996 }
5046 4997
5047 // Runtime functions should not return 'the hole'. Allowing it to escape may 4998 // Runtime functions should not return 'the hole'. Allowing it to escape may
5048 // lead to crashes in the IC code later. 4999 // lead to crashes in the IC code later.
5049 if (FLAG_debug_code) { 5000 if (FLAG_debug_code) {
5050 Label okay; 5001 Label okay;
5051 __ cmp(eax, masm->isolate()->factory()->the_hole_value()); 5002 __ cmp(eax, masm->isolate()->factory()->the_hole_value());
5052 __ j(not_equal, &okay, Label::kNear); 5003 __ j(not_equal, &okay, Label::kNear);
5053 // TODO(wingo): Currently SuspendJSGeneratorObject returns the hole. Change
5054 // to return another sentinel like a harmony symbol.
5055 __ cmp(ebx, Immediate(ExternalReference(
5056 Runtime::kSuspendJSGeneratorObject, masm->isolate())));
5057 __ j(equal, &okay, Label::kNear);
5058 __ int3(); 5004 __ int3();
5059 __ bind(&okay); 5005 __ bind(&okay);
5060 } 5006 }
5061 5007
5062 // Check for failure result. 5008 // Check for failure result.
5063 Label failure_returned; 5009 Label failure_returned;
5064 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); 5010 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
5065 __ lea(ecx, Operand(eax, 1)); 5011 __ lea(ecx, Operand(eax, 1));
5066 // Lower 2 bits of ecx are 0 iff eax has failure tag. 5012 // Lower 2 bits of ecx are 0 iff eax has failure tag.
5067 __ test(ecx, Immediate(kFailureTagMask)); 5013 __ test(ecx, Immediate(kFailureTagMask));
(...skipping 1832 matching lines...) Expand 10 before | Expand all | Expand 10 after
6900 STATIC_ASSERT(kSmiTag == 0); 6846 STATIC_ASSERT(kSmiTag == 0);
6901 __ and_(tmp1, right); 6847 __ and_(tmp1, right);
6902 __ JumpIfSmi(tmp1, &miss, Label::kNear); 6848 __ JumpIfSmi(tmp1, &miss, Label::kNear);
6903 6849
6904 // Check that both operands are internalized strings. 6850 // Check that both operands are internalized strings.
6905 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 6851 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
6906 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 6852 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
6907 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 6853 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
6908 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 6854 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
6909 STATIC_ASSERT(kInternalizedTag != 0); 6855 STATIC_ASSERT(kInternalizedTag != 0);
6910 __ and_(tmp1, tmp2); 6856 __ and_(tmp1, Immediate(kIsNotStringMask | kIsInternalizedMask));
6911 __ test(tmp1, Immediate(kIsInternalizedMask)); 6857 __ cmpb(tmp1, kInternalizedTag | kStringTag);
6912 __ j(zero, &miss, Label::kNear); 6858 __ j(not_equal, &miss, Label::kNear);
6859
6860 __ and_(tmp2, Immediate(kIsNotStringMask | kIsInternalizedMask));
6861 __ cmpb(tmp2, kInternalizedTag | kStringTag);
6862 __ j(not_equal, &miss, Label::kNear);
6913 6863
6914 // Internalized strings are compared by identity. 6864 // Internalized strings are compared by identity.
6915 Label done; 6865 Label done;
6916 __ cmp(left, right); 6866 __ cmp(left, right);
6917 // Make sure eax is non-zero. At this point input operands are 6867 // Make sure eax is non-zero. At this point input operands are
6918 // guaranteed to be non-zero. 6868 // guaranteed to be non-zero.
6919 ASSERT(right.is(eax)); 6869 ASSERT(right.is(eax));
6920 __ j(not_equal, &done, Label::kNear); 6870 __ j(not_equal, &done, Label::kNear);
6921 STATIC_ASSERT(EQUAL == 0); 6871 STATIC_ASSERT(EQUAL == 0);
6922 STATIC_ASSERT(kSmiTag == 0); 6872 STATIC_ASSERT(kSmiTag == 0);
(...skipping 24 matching lines...) Expand all
6947 __ JumpIfSmi(tmp1, &miss, Label::kNear); 6897 __ JumpIfSmi(tmp1, &miss, Label::kNear);
6948 6898
6949 // Check that both operands are unique names. This leaves the instance 6899 // Check that both operands are unique names. This leaves the instance
6950 // types loaded in tmp1 and tmp2. 6900 // types loaded in tmp1 and tmp2.
6951 STATIC_ASSERT(kInternalizedTag != 0); 6901 STATIC_ASSERT(kInternalizedTag != 0);
6952 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 6902 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
6953 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 6903 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
6954 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 6904 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
6955 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 6905 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
6956 6906
6957 Label succeed1; 6907 __ JumpIfNotUniqueName(tmp1, &miss, Label::kNear);
6958 __ test(tmp1, Immediate(kIsInternalizedMask)); 6908 __ JumpIfNotUniqueName(tmp2, &miss, Label::kNear);
6959 __ j(not_zero, &succeed1);
6960 __ cmpb(tmp1, static_cast<uint8_t>(SYMBOL_TYPE));
6961 __ j(not_equal, &miss);
6962 __ bind(&succeed1);
6963
6964 Label succeed2;
6965 __ test(tmp2, Immediate(kIsInternalizedMask));
6966 __ j(not_zero, &succeed2);
6967 __ cmpb(tmp2, static_cast<uint8_t>(SYMBOL_TYPE));
6968 __ j(not_equal, &miss);
6969 __ bind(&succeed2);
6970 6909
6971 // Unique names are compared by identity. 6910 // Unique names are compared by identity.
6972 Label done; 6911 Label done;
6973 __ cmp(left, right); 6912 __ cmp(left, right);
6974 // Make sure eax is non-zero. At this point input operands are 6913 // Make sure eax is non-zero. At this point input operands are
6975 // guaranteed to be non-zero. 6914 // guaranteed to be non-zero.
6976 ASSERT(right.is(eax)); 6915 ASSERT(right.is(eax));
6977 __ j(not_equal, &done, Label::kNear); 6916 __ j(not_equal, &done, Label::kNear);
6978 STATIC_ASSERT(EQUAL == 0); 6917 STATIC_ASSERT(EQUAL == 0);
6979 STATIC_ASSERT(kSmiTag == 0); 6918 STATIC_ASSERT(kSmiTag == 0);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
7024 STATIC_ASSERT(EQUAL == 0); 6963 STATIC_ASSERT(EQUAL == 0);
7025 STATIC_ASSERT(kSmiTag == 0); 6964 STATIC_ASSERT(kSmiTag == 0);
7026 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 6965 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
7027 __ ret(0); 6966 __ ret(0);
7028 6967
7029 // Handle not identical strings. 6968 // Handle not identical strings.
7030 __ bind(&not_same); 6969 __ bind(&not_same);
7031 6970
7032 // Check that both strings are internalized. If they are, we're done 6971 // Check that both strings are internalized. If they are, we're done
7033 // because we already know they are not identical. But in the case of 6972 // because we already know they are not identical. But in the case of
7034 // non-equality compare, we still need to determine the order. 6973 // non-equality compare, we still need to determine the order. We
6974 // also know they are both strings.
7035 if (equality) { 6975 if (equality) {
7036 Label do_compare; 6976 Label do_compare;
7037 STATIC_ASSERT(kInternalizedTag != 0); 6977 STATIC_ASSERT(kInternalizedTag != 0);
7038 __ and_(tmp1, tmp2); 6978 __ and_(tmp1, tmp2);
7039 __ test(tmp1, Immediate(kIsInternalizedMask)); 6979 __ test(tmp1, Immediate(kIsInternalizedMask));
7040 __ j(zero, &do_compare, Label::kNear); 6980 __ j(zero, &do_compare, Label::kNear);
7041 // Make sure eax is non-zero. At this point input operands are 6981 // Make sure eax is non-zero. At this point input operands are
7042 // guaranteed to be non-zero. 6982 // guaranteed to be non-zero.
7043 ASSERT(right.is(eax)); 6983 ASSERT(right.is(eax));
7044 __ ret(0); 6984 __ ret(0);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
7183 __ cmp(entity_name, Handle<Name>(name)); 7123 __ cmp(entity_name, Handle<Name>(name));
7184 __ j(equal, miss); 7124 __ j(equal, miss);
7185 7125
7186 Label good; 7126 Label good;
7187 // Check for the hole and skip. 7127 // Check for the hole and skip.
7188 __ cmp(entity_name, masm->isolate()->factory()->the_hole_value()); 7128 __ cmp(entity_name, masm->isolate()->factory()->the_hole_value());
7189 __ j(equal, &good, Label::kNear); 7129 __ j(equal, &good, Label::kNear);
7190 7130
7191 // Check if the entry name is not a unique name. 7131 // Check if the entry name is not a unique name.
7192 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); 7132 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
7193 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), 7133 __ JumpIfNotUniqueName(FieldOperand(entity_name, Map::kInstanceTypeOffset),
7194 kIsInternalizedMask); 7134 miss);
7195 __ j(not_zero, &good);
7196 __ cmpb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
7197 static_cast<uint8_t>(SYMBOL_TYPE));
7198 __ j(not_equal, miss);
7199 __ bind(&good); 7135 __ bind(&good);
7200 } 7136 }
7201 7137
7202 NameDictionaryLookupStub stub(properties, r0, r0, NEGATIVE_LOOKUP); 7138 NameDictionaryLookupStub stub(properties, r0, r0, NEGATIVE_LOOKUP);
7203 __ push(Immediate(Handle<Object>(name))); 7139 __ push(Immediate(Handle<Object>(name)));
7204 __ push(Immediate(name->Hash())); 7140 __ push(Immediate(name->Hash()));
7205 __ CallStub(&stub); 7141 __ CallStub(&stub);
7206 __ test(r0, r0); 7142 __ test(r0, r0);
7207 __ j(not_zero, miss); 7143 __ j(not_zero, miss);
7208 __ jmp(done); 7144 __ jmp(done);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
7321 // Stop if found the property. 7257 // Stop if found the property.
7322 __ cmp(scratch, Operand(esp, 3 * kPointerSize)); 7258 __ cmp(scratch, Operand(esp, 3 * kPointerSize));
7323 __ j(equal, &in_dictionary); 7259 __ j(equal, &in_dictionary);
7324 7260
7325 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { 7261 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
7326 // If we hit a key that is not a unique name during negative 7262 // If we hit a key that is not a unique name during negative
7327 // lookup we have to bailout as this key might be equal to the 7263 // lookup we have to bailout as this key might be equal to the
7328 // key we are looking for. 7264 // key we are looking for.
7329 7265
7330 // Check if the entry name is not a unique name. 7266 // Check if the entry name is not a unique name.
7331 Label cont;
7332 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 7267 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
7333 __ test_b(FieldOperand(scratch, Map::kInstanceTypeOffset), 7268 __ JumpIfNotUniqueName(FieldOperand(scratch, Map::kInstanceTypeOffset),
7334 kIsInternalizedMask); 7269 &maybe_in_dictionary);
7335 __ j(not_zero, &cont);
7336 __ cmpb(FieldOperand(scratch, Map::kInstanceTypeOffset),
7337 static_cast<uint8_t>(SYMBOL_TYPE));
7338 __ j(not_equal, &maybe_in_dictionary);
7339 __ bind(&cont);
7340 } 7270 }
7341 } 7271 }
7342 7272
7343 __ bind(&maybe_in_dictionary); 7273 __ bind(&maybe_in_dictionary);
7344 // If we are doing negative lookup then probing failure should be 7274 // If we are doing negative lookup then probing failure should be
7345 // treated as a lookup success. For positive lookup probing failure 7275 // treated as a lookup success. For positive lookup probing failure
7346 // should be treated as lookup failure. 7276 // should be treated as lookup failure.
7347 if (mode_ == POSITIVE_LOOKUP) { 7277 if (mode_ == POSITIVE_LOOKUP) {
7348 __ mov(result_, Immediate(0)); 7278 __ mov(result_, Immediate(0));
7349 __ Drop(1); 7279 __ Drop(1);
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
7938 // We should either have undefined in ebx or a valid cell 7868 // We should either have undefined in ebx or a valid cell
7939 Label okay_here; 7869 Label okay_here;
7940 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); 7870 Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
7941 __ cmp(ebx, Immediate(undefined_sentinel)); 7871 __ cmp(ebx, Immediate(undefined_sentinel));
7942 __ j(equal, &okay_here); 7872 __ j(equal, &okay_here);
7943 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map)); 7873 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map));
7944 __ Assert(equal, "Expected property cell in register ebx"); 7874 __ Assert(equal, "Expected property cell in register ebx");
7945 __ bind(&okay_here); 7875 __ bind(&okay_here);
7946 } 7876 }
7947 7877
7948 if (FLAG_optimize_constructed_arrays) { 7878 Label no_info, switch_ready;
7949 Label no_info, switch_ready; 7879 // Get the elements kind and case on that.
7950 // Get the elements kind and case on that. 7880 __ cmp(ebx, Immediate(undefined_sentinel));
7951 __ cmp(ebx, Immediate(undefined_sentinel)); 7881 __ j(equal, &no_info);
7952 __ j(equal, &no_info); 7882 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset));
7953 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); 7883 __ JumpIfNotSmi(edx, &no_info);
7954 __ JumpIfNotSmi(edx, &no_info); 7884 __ SmiUntag(edx);
7955 __ SmiUntag(edx); 7885 __ jmp(&switch_ready);
7956 __ jmp(&switch_ready); 7886 __ bind(&no_info);
7957 __ bind(&no_info); 7887 __ mov(edx, Immediate(GetInitialFastElementsKind()));
7958 __ mov(edx, Immediate(GetInitialFastElementsKind())); 7888 __ bind(&switch_ready);
7959 __ bind(&switch_ready);
7960 7889
7961 if (argument_count_ == ANY) { 7890 if (argument_count_ == ANY) {
7962 Label not_zero_case, not_one_case; 7891 Label not_zero_case, not_one_case;
7963 __ test(eax, eax); 7892 __ test(eax, eax);
7964 __ j(not_zero, &not_zero_case); 7893 __ j(not_zero, &not_zero_case);
7965 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); 7894 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
7966 7895
7967 __ bind(&not_zero_case); 7896 __ bind(&not_zero_case);
7968 __ cmp(eax, 1); 7897 __ cmp(eax, 1);
7969 __ j(greater, &not_one_case); 7898 __ j(greater, &not_one_case);
7970 CreateArrayDispatchOneArgument(masm); 7899 CreateArrayDispatchOneArgument(masm);
7971 7900
7972 __ bind(&not_one_case); 7901 __ bind(&not_one_case);
7973 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); 7902 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7974 } else if (argument_count_ == NONE) { 7903 } else if (argument_count_ == NONE) {
7975 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); 7904 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
7976 } else if (argument_count_ == ONE) { 7905 } else if (argument_count_ == ONE) {
7977 CreateArrayDispatchOneArgument(masm); 7906 CreateArrayDispatchOneArgument(masm);
7978 } else if (argument_count_ == MORE_THAN_ONE) { 7907 } else if (argument_count_ == MORE_THAN_ONE) {
7979 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); 7908 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7980 } else {
7981 UNREACHABLE();
7982 }
7983 } else { 7909 } else {
7984 Label generic_constructor; 7910 UNREACHABLE();
7985 // Run the native code for the Array function called as constructor.
7986 ArrayNativeCode(masm, true, &generic_constructor);
7987
7988 // Jump to the generic construct code in case the specialized code cannot
7989 // handle the construction.
7990 __ bind(&generic_constructor);
7991 Handle<Code> generic_construct_stub =
7992 masm->isolate()->builtins()->JSConstructStubGeneric();
7993 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
7994 } 7911 }
7995 } 7912 }
7996 7913
7997 7914
7998 void InternalArrayConstructorStub::GenerateCase( 7915 void InternalArrayConstructorStub::GenerateCase(
7999 MacroAssembler* masm, ElementsKind kind) { 7916 MacroAssembler* masm, ElementsKind kind) {
8000 Label not_zero_case, not_one_case; 7917 Label not_zero_case, not_one_case;
8001 Label normal_sequence; 7918 Label normal_sequence;
8002 7919
8003 __ test(eax, eax); 7920 __ test(eax, eax);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
8046 7963
8047 // Initial map for the builtin Array function should be a map. 7964 // Initial map for the builtin Array function should be a map.
8048 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 7965 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
8049 // Will both indicate a NULL and a Smi. 7966 // Will both indicate a NULL and a Smi.
8050 __ test(ecx, Immediate(kSmiTagMask)); 7967 __ test(ecx, Immediate(kSmiTagMask));
8051 __ Assert(not_zero, "Unexpected initial map for Array function"); 7968 __ Assert(not_zero, "Unexpected initial map for Array function");
8052 __ CmpObjectType(ecx, MAP_TYPE, ecx); 7969 __ CmpObjectType(ecx, MAP_TYPE, ecx);
8053 __ Assert(equal, "Unexpected initial map for Array function"); 7970 __ Assert(equal, "Unexpected initial map for Array function");
8054 } 7971 }
8055 7972
8056 if (FLAG_optimize_constructed_arrays) { 7973 // Figure out the right elements kind
8057 // Figure out the right elements kind 7974 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
8058 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
8059 7975
8060 // Load the map's "bit field 2" into |result|. We only need the first byte, 7976 // Load the map's "bit field 2" into |result|. We only need the first byte,
8061 // but the following masking takes care of that anyway. 7977 // but the following masking takes care of that anyway.
8062 __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); 7978 __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset));
8063 // Retrieve elements_kind from bit field 2. 7979 // Retrieve elements_kind from bit field 2.
8064 __ and_(ecx, Map::kElementsKindMask); 7980 __ and_(ecx, Map::kElementsKindMask);
8065 __ shr(ecx, Map::kElementsKindShift); 7981 __ shr(ecx, Map::kElementsKindShift);
8066 7982
8067 if (FLAG_debug_code) { 7983 if (FLAG_debug_code) {
8068 Label done; 7984 Label done;
8069 __ cmp(ecx, Immediate(FAST_ELEMENTS)); 7985 __ cmp(ecx, Immediate(FAST_ELEMENTS));
8070 __ j(equal, &done); 7986 __ j(equal, &done);
8071 __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS)); 7987 __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS));
8072 __ Assert(equal, 7988 __ Assert(equal,
8073 "Invalid ElementsKind for InternalArray or InternalPackedArray"); 7989 "Invalid ElementsKind for InternalArray or InternalPackedArray");
8074 __ bind(&done); 7990 __ bind(&done);
8075 } 7991 }
8076 7992
8077 Label fast_elements_case; 7993 Label fast_elements_case;
8078 __ cmp(ecx, Immediate(FAST_ELEMENTS)); 7994 __ cmp(ecx, Immediate(FAST_ELEMENTS));
8079 __ j(equal, &fast_elements_case); 7995 __ j(equal, &fast_elements_case);
8080 GenerateCase(masm, FAST_HOLEY_ELEMENTS); 7996 GenerateCase(masm, FAST_HOLEY_ELEMENTS);
8081 7997
8082 __ bind(&fast_elements_case); 7998 __ bind(&fast_elements_case);
8083 GenerateCase(masm, FAST_ELEMENTS); 7999 GenerateCase(masm, FAST_ELEMENTS);
8084 } else {
8085 Label generic_constructor;
8086 // Run the native code for the Array function called as constructor.
8087 ArrayNativeCode(masm, true, &generic_constructor);
8088
8089 // Jump to the generic construct code in case the specialized code cannot
8090 // handle the construction.
8091 __ bind(&generic_constructor);
8092 Handle<Code> generic_construct_stub =
8093 masm->isolate()->builtins()->JSConstructStubGeneric();
8094 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
8095 }
8096 } 8000 }
8097 8001
8098 8002
8099 #undef __ 8003 #undef __
8100 8004
8101 } } // namespace v8::internal 8005 } } // namespace v8::internal
8102 8006
8103 #endif // V8_TARGET_ARCH_IA32 8007 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/frames-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698