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

Side by Side Diff: src/arm/code-stubs-arm.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/arm/builtins-arm.cc ('k') | src/arm/frames-arm.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 874 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 885
886 __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE); 886 __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE);
887 __ b(ge, &return_not_equal); 887 __ b(ge, &return_not_equal);
888 888
889 // Check for oddballs: true, false, null, undefined. 889 // Check for oddballs: true, false, null, undefined.
890 __ cmp(r3, Operand(ODDBALL_TYPE)); 890 __ cmp(r3, Operand(ODDBALL_TYPE));
891 __ b(eq, &return_not_equal); 891 __ b(eq, &return_not_equal);
892 892
893 // Now that we have the types we might as well check for 893 // Now that we have the types we might as well check for
894 // internalized-internalized. 894 // internalized-internalized.
895 // Ensure that no non-strings have the internalized bit set. 895 Label not_internalized;
896 STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsInternalizedMask);
897 STATIC_ASSERT(kInternalizedTag != 0); 896 STATIC_ASSERT(kInternalizedTag != 0);
898 __ and_(r2, r2, Operand(r3)); 897 __ and_(r2, r2, Operand(kIsNotStringMask | kIsInternalizedMask));
899 __ tst(r2, Operand(kIsInternalizedMask)); 898 __ cmp(r2, Operand(kInternalizedTag | kStringTag));
900 __ b(ne, &return_not_equal); 899 __ b(ne, &not_internalized); // r2 (rhs) is not an internalized string
900
901 __ and_(r3, r3, Operand(kIsNotStringMask | kIsInternalizedMask));
902 __ cmp(r3, Operand(kInternalizedTag | kStringTag));
903 __ b(eq, &return_not_equal); // both rhs and lhs are internalized strings
904
905 __ bind(&not_internalized);
901 } 906 }
902 907
903 908
904 // See comment at call site. 909 // See comment at call site.
905 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, 910 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
906 Register lhs, 911 Register lhs,
907 Register rhs, 912 Register rhs,
908 Label* both_loaded_as_doubles, 913 Label* both_loaded_as_doubles,
909 Label* not_heap_numbers, 914 Label* not_heap_numbers,
910 Label* slow) { 915 Label* slow) {
(...skipping 19 matching lines...) Expand all
930 // Fast negative check for internalized-to-internalized equality. 935 // Fast negative check for internalized-to-internalized equality.
931 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, 936 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
932 Register lhs, 937 Register lhs,
933 Register rhs, 938 Register rhs,
934 Label* possible_strings, 939 Label* possible_strings,
935 Label* not_both_strings) { 940 Label* not_both_strings) {
936 ASSERT((lhs.is(r0) && rhs.is(r1)) || 941 ASSERT((lhs.is(r0) && rhs.is(r1)) ||
937 (lhs.is(r1) && rhs.is(r0))); 942 (lhs.is(r1) && rhs.is(r0)));
938 943
939 // r2 is object type of rhs. 944 // r2 is object type of rhs.
940 // Ensure that no non-strings have the internalized bit set.
941 Label object_test; 945 Label object_test;
942 STATIC_ASSERT(kInternalizedTag != 0); 946 STATIC_ASSERT(kInternalizedTag != 0);
943 __ tst(r2, Operand(kIsNotStringMask)); 947 __ tst(r2, Operand(kIsNotStringMask));
944 __ b(ne, &object_test); 948 __ b(ne, &object_test);
945 __ tst(r2, Operand(kIsInternalizedMask)); 949 __ tst(r2, Operand(kIsInternalizedMask));
946 __ b(eq, possible_strings); 950 __ b(eq, possible_strings);
947 __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE); 951 __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE);
948 __ b(ge, not_both_strings); 952 __ b(ge, not_both_strings);
949 __ tst(r3, Operand(kIsInternalizedMask)); 953 __ tst(r3, Operand(kIsInternalizedMask));
950 __ b(eq, possible_strings); 954 __ b(eq, possible_strings);
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2068 masm, BinaryOpIC::UNINITIALIZED, BinaryOpIC::UNINITIALIZED, true, 2072 masm, BinaryOpIC::UNINITIALIZED, BinaryOpIC::UNINITIALIZED, true,
2069 use_runtime, gc_required, &not_smis, op, mode); 2073 use_runtime, gc_required, &not_smis, op, mode);
2070 } 2074 }
2071 __ bind(&not_smis); 2075 __ bind(&not_smis);
2072 } 2076 }
2073 2077
2074 2078
2075 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 2079 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
2076 Label right_arg_changed, call_runtime; 2080 Label right_arg_changed, call_runtime;
2077 2081
2078 if (op_ == Token::MOD && has_fixed_right_arg_) { 2082 if (op_ == Token::MOD && encoded_right_arg_.has_value) {
2079 // It is guaranteed that the value will fit into a Smi, because if it 2083 // It is guaranteed that the value will fit into a Smi, because if it
2080 // didn't, we wouldn't be here, see BinaryOp_Patch. 2084 // didn't, we wouldn't be here, see BinaryOp_Patch.
2081 __ cmp(r0, Operand(Smi::FromInt(fixed_right_arg_value()))); 2085 __ cmp(r0, Operand(Smi::FromInt(fixed_right_arg_value())));
2082 __ b(ne, &right_arg_changed); 2086 __ b(ne, &right_arg_changed);
2083 } 2087 }
2084 2088
2085 if (result_type_ == BinaryOpIC::UNINITIALIZED || 2089 if (result_type_ == BinaryOpIC::UNINITIALIZED ||
2086 result_type_ == BinaryOpIC::SMI) { 2090 result_type_ == BinaryOpIC::SMI) {
2087 // Only allow smi results. 2091 // Only allow smi results.
2088 BinaryOpStub_GenerateSmiCode( 2092 BinaryOpStub_GenerateSmiCode(
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
2245 mode_); 2249 mode_);
2246 __ sub(r0, heap_number_result, Operand(kHeapObjectTag)); 2250 __ sub(r0, heap_number_result, Operand(kHeapObjectTag));
2247 __ vstr(d5, r0, HeapNumber::kValueOffset); 2251 __ vstr(d5, r0, HeapNumber::kValueOffset);
2248 __ mov(r0, heap_number_result); 2252 __ mov(r0, heap_number_result);
2249 __ Ret(); 2253 __ Ret();
2250 2254
2251 // A DIV operation expecting an integer result falls through 2255 // A DIV operation expecting an integer result falls through
2252 // to type transition. 2256 // to type transition.
2253 2257
2254 } else { 2258 } else {
2255 if (has_fixed_right_arg_) { 2259 if (encoded_right_arg_.has_value) {
2256 __ Vmov(d8, fixed_right_arg_value(), scratch1); 2260 __ Vmov(d8, fixed_right_arg_value(), scratch1);
2257 __ VFPCompareAndSetFlags(d1, d8); 2261 __ VFPCompareAndSetFlags(d1, d8);
2258 __ b(ne, &transition); 2262 __ b(ne, &transition);
2259 } 2263 }
2260 2264
2261 // We preserved r0 and r1 to be able to call runtime. 2265 // We preserved r0 and r1 to be able to call runtime.
2262 // Save the left value on the stack. 2266 // Save the left value on the stack.
2263 __ Push(r5, r4); 2267 __ Push(r5, r4);
2264 2268
2265 Label pop_and_call_runtime; 2269 Label pop_and_call_runtime;
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after
2989 result_size_ == 1; 2993 result_size_ == 1;
2990 } 2994 }
2991 2995
2992 2996
2993 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 2997 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
2994 CEntryStub::GenerateAheadOfTime(isolate); 2998 CEntryStub::GenerateAheadOfTime(isolate);
2995 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); 2999 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate);
2996 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 3000 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2997 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 3001 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
2998 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); 3002 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate);
2999 if (FLAG_optimize_constructed_arrays) { 3003 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
3000 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
3001 }
3002 } 3004 }
3003 3005
3004 3006
3005 void CodeStub::GenerateFPStubs(Isolate* isolate) { 3007 void CodeStub::GenerateFPStubs(Isolate* isolate) {
3006 SaveFPRegsMode mode = kSaveFPRegs; 3008 SaveFPRegsMode mode = kSaveFPRegs;
3007 CEntryStub save_doubles(1, mode); 3009 CEntryStub save_doubles(1, mode);
3008 StoreBufferOverflowStub stub(mode); 3010 StoreBufferOverflowStub stub(mode);
3009 // These stubs might already be in the snapshot, detect that and don't 3011 // These stubs might already be in the snapshot, detect that and don't
3010 // regenerate, which would lead to code stub initialization state being messed 3012 // regenerate, which would lead to code stub initialization state being messed
3011 // up. 3013 // up.
(...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after
4616 4618
4617 __ bind(&done); 4619 __ bind(&done);
4618 __ add(sp, sp, Operand(3 * kPointerSize)); 4620 __ add(sp, sp, Operand(3 * kPointerSize));
4619 __ Ret(); 4621 __ Ret();
4620 4622
4621 __ bind(&slowcase); 4623 __ bind(&slowcase);
4622 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); 4624 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1);
4623 } 4625 }
4624 4626
4625 4627
4626 static void GenerateRecordCallTargetNoArray(MacroAssembler* masm) {
4627 // Cache the called function in a global property cell. Cache states
4628 // are uninitialized, monomorphic (indicated by a JSFunction), and
4629 // megamorphic.
4630 // r1 : the function to call
4631 // r2 : cache cell for call target
4632 Label done;
4633
4634 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
4635 masm->isolate()->heap()->undefined_value());
4636 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()),
4637 masm->isolate()->heap()->the_hole_value());
4638
4639 // Load the cache state into r3.
4640 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
4641
4642 // A monomorphic cache hit or an already megamorphic state: invoke the
4643 // function without changing the state.
4644 __ cmp(r3, r1);
4645 __ b(eq, &done);
4646 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex);
4647 __ b(eq, &done);
4648
4649 // A monomorphic miss (i.e, here the cache is not uninitialized) goes
4650 // megamorphic.
4651 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
4652 // MegamorphicSentinel is an immortal immovable object (undefined) so no
4653 // write-barrier is needed.
4654 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex, ne);
4655 __ str(ip, FieldMemOperand(r2, Cell::kValueOffset), ne);
4656
4657 // An uninitialized cache is patched with the function.
4658 __ str(r1, FieldMemOperand(r2, Cell::kValueOffset), eq);
4659 // No need for a write barrier here - cells are rescanned.
4660
4661 __ bind(&done);
4662 }
4663
4664
4665 static void GenerateRecordCallTarget(MacroAssembler* masm) { 4628 static void GenerateRecordCallTarget(MacroAssembler* masm) {
4666 // Cache the called function in a global property cell. Cache states 4629 // Cache the called function in a global property cell. Cache states
4667 // are uninitialized, monomorphic (indicated by a JSFunction), and 4630 // are uninitialized, monomorphic (indicated by a JSFunction), and
4668 // megamorphic. 4631 // megamorphic.
4669 // r1 : the function to call 4632 // r1 : the function to call
4670 // r2 : cache cell for call target 4633 // r2 : cache cell for call target
4671 ASSERT(FLAG_optimize_constructed_arrays);
4672 Label initialize, done, miss, megamorphic, not_array_function; 4634 Label initialize, done, miss, megamorphic, not_array_function;
4673 4635
4674 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), 4636 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
4675 masm->isolate()->heap()->undefined_value()); 4637 masm->isolate()->heap()->undefined_value());
4676 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), 4638 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()),
4677 masm->isolate()->heap()->the_hole_value()); 4639 masm->isolate()->heap()->the_hole_value());
4678 4640
4679 // Load the cache state into r3. 4641 // Load the cache state into r3.
4680 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); 4642 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
4681 4643
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
4765 } 4727 }
4766 4728
4767 // Check that the function is really a JavaScript function. 4729 // Check that the function is really a JavaScript function.
4768 // r1: pushed function (to be verified) 4730 // r1: pushed function (to be verified)
4769 __ JumpIfSmi(r1, &non_function); 4731 __ JumpIfSmi(r1, &non_function);
4770 // Get the map of the function object. 4732 // Get the map of the function object.
4771 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 4733 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
4772 __ b(ne, &slow); 4734 __ b(ne, &slow);
4773 4735
4774 if (RecordCallTarget()) { 4736 if (RecordCallTarget()) {
4775 if (FLAG_optimize_constructed_arrays) { 4737 GenerateRecordCallTarget(masm);
4776 GenerateRecordCallTarget(masm);
4777 } else {
4778 GenerateRecordCallTargetNoArray(masm);
4779 }
4780 } 4738 }
4781 4739
4782 // Fast-case: Invoke the function now. 4740 // Fast-case: Invoke the function now.
4783 // r1: pushed function 4741 // r1: pushed function
4784 ParameterCount actual(argc_); 4742 ParameterCount actual(argc_);
4785 4743
4786 if (ReceiverMightBeImplicit()) { 4744 if (ReceiverMightBeImplicit()) {
4787 Label call_as_function; 4745 Label call_as_function;
4788 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); 4746 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
4789 __ b(eq, &call_as_function); 4747 __ b(eq, &call_as_function);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
4844 // r2 : cache cell for call target 4802 // r2 : cache cell for call target
4845 Label slow, non_function_call; 4803 Label slow, non_function_call;
4846 4804
4847 // Check that the function is not a smi. 4805 // Check that the function is not a smi.
4848 __ JumpIfSmi(r1, &non_function_call); 4806 __ JumpIfSmi(r1, &non_function_call);
4849 // Check that the function is a JSFunction. 4807 // Check that the function is a JSFunction.
4850 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 4808 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
4851 __ b(ne, &slow); 4809 __ b(ne, &slow);
4852 4810
4853 if (RecordCallTarget()) { 4811 if (RecordCallTarget()) {
4854 if (FLAG_optimize_constructed_arrays) { 4812 GenerateRecordCallTarget(masm);
4855 GenerateRecordCallTarget(masm);
4856 } else {
4857 GenerateRecordCallTargetNoArray(masm);
4858 }
4859 } 4813 }
4860 4814
4861 // Jump to the function-specific construct stub. 4815 // Jump to the function-specific construct stub.
4862 Register jmp_reg = FLAG_optimize_constructed_arrays ? r3 : r2; 4816 Register jmp_reg = r3;
4863 __ ldr(jmp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 4817 __ ldr(jmp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
4864 __ ldr(jmp_reg, FieldMemOperand(jmp_reg, 4818 __ ldr(jmp_reg, FieldMemOperand(jmp_reg,
4865 SharedFunctionInfo::kConstructStubOffset)); 4819 SharedFunctionInfo::kConstructStubOffset));
4866 __ add(pc, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); 4820 __ add(pc, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
4867 4821
4868 // r0: number of arguments 4822 // r0: number of arguments
4869 // r1: called object 4823 // r1: called object
4870 // r3: object type 4824 // r3: object type
4871 Label do_call; 4825 Label do_call;
4872 __ bind(&slow); 4826 __ bind(&slow);
(...skipping 1383 matching lines...) Expand 10 before | Expand all | Expand 10 after
6256 6210
6257 // Check that both operands are heap objects. 6211 // Check that both operands are heap objects.
6258 __ JumpIfEitherSmi(left, right, &miss); 6212 __ JumpIfEitherSmi(left, right, &miss);
6259 6213
6260 // Check that both operands are internalized strings. 6214 // Check that both operands are internalized strings.
6261 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 6215 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
6262 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 6216 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
6263 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 6217 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
6264 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 6218 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
6265 STATIC_ASSERT(kInternalizedTag != 0); 6219 STATIC_ASSERT(kInternalizedTag != 0);
6266 __ and_(tmp1, tmp1, Operand(tmp2)); 6220
6267 __ tst(tmp1, Operand(kIsInternalizedMask)); 6221 __ and_(tmp1, tmp1, Operand(kIsNotStringMask | kIsInternalizedMask));
6268 __ b(eq, &miss); 6222 __ cmp(tmp1, Operand(kInternalizedTag | kStringTag));
6223 __ b(ne, &miss);
6224
6225 __ and_(tmp2, tmp2, Operand(kIsNotStringMask | kIsInternalizedMask));
6226 __ cmp(tmp2, Operand(kInternalizedTag | kStringTag));
6227 __ b(ne, &miss);
6269 6228
6270 // Internalized strings are compared by identity. 6229 // Internalized strings are compared by identity.
6271 __ cmp(left, right); 6230 __ cmp(left, right);
6272 // Make sure r0 is non-zero. At this point input operands are 6231 // Make sure r0 is non-zero. At this point input operands are
6273 // guaranteed to be non-zero. 6232 // guaranteed to be non-zero.
6274 ASSERT(right.is(r0)); 6233 ASSERT(right.is(r0));
6275 STATIC_ASSERT(EQUAL == 0); 6234 STATIC_ASSERT(EQUAL == 0);
6276 STATIC_ASSERT(kSmiTag == 0); 6235 STATIC_ASSERT(kSmiTag == 0);
6277 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 6236 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
6278 __ Ret(); 6237 __ Ret();
(...skipping 18 matching lines...) Expand all
6297 __ JumpIfEitherSmi(left, right, &miss); 6256 __ JumpIfEitherSmi(left, right, &miss);
6298 6257
6299 // Check that both operands are unique names. This leaves the instance 6258 // Check that both operands are unique names. This leaves the instance
6300 // types loaded in tmp1 and tmp2. 6259 // types loaded in tmp1 and tmp2.
6301 STATIC_ASSERT(kInternalizedTag != 0); 6260 STATIC_ASSERT(kInternalizedTag != 0);
6302 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 6261 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
6303 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 6262 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
6304 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 6263 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
6305 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 6264 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
6306 6265
6307 Label succeed1; 6266 __ JumpIfNotUniqueName(tmp1, &miss);
6308 __ tst(tmp1, Operand(kIsInternalizedMask)); 6267 __ JumpIfNotUniqueName(tmp2, &miss);
6309 __ b(ne, &succeed1);
6310 __ cmp(tmp1, Operand(SYMBOL_TYPE));
6311 __ b(ne, &miss);
6312 __ bind(&succeed1);
6313
6314 Label succeed2;
6315 __ tst(tmp2, Operand(kIsInternalizedMask));
6316 __ b(ne, &succeed2);
6317 __ cmp(tmp2, Operand(SYMBOL_TYPE));
6318 __ b(ne, &miss);
6319 __ bind(&succeed2);
6320 6268
6321 // Unique names are compared by identity. 6269 // Unique names are compared by identity.
6322 __ cmp(left, right); 6270 __ cmp(left, right);
6323 // Make sure r0 is non-zero. At this point input operands are 6271 // Make sure r0 is non-zero. At this point input operands are
6324 // guaranteed to be non-zero. 6272 // guaranteed to be non-zero.
6325 ASSERT(right.is(r0)); 6273 ASSERT(right.is(r0));
6326 STATIC_ASSERT(EQUAL == 0); 6274 STATIC_ASSERT(EQUAL == 0);
6327 STATIC_ASSERT(kSmiTag == 0); 6275 STATIC_ASSERT(kSmiTag == 0);
6328 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 6276 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
6329 __ Ret(); 6277 __ Ret();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
6364 // Fast check for identical strings. 6312 // Fast check for identical strings.
6365 __ cmp(left, right); 6313 __ cmp(left, right);
6366 STATIC_ASSERT(EQUAL == 0); 6314 STATIC_ASSERT(EQUAL == 0);
6367 STATIC_ASSERT(kSmiTag == 0); 6315 STATIC_ASSERT(kSmiTag == 0);
6368 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 6316 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
6369 __ Ret(eq); 6317 __ Ret(eq);
6370 6318
6371 // Handle not identical strings. 6319 // Handle not identical strings.
6372 6320
6373 // Check that both strings are internalized strings. If they are, we're done 6321 // Check that both strings are internalized strings. If they are, we're done
6374 // because we already know they are not identical. 6322 // because we already know they are not identical. We know they are both
6323 // strings.
6375 if (equality) { 6324 if (equality) {
6376 ASSERT(GetCondition() == eq); 6325 ASSERT(GetCondition() == eq);
6377 STATIC_ASSERT(kInternalizedTag != 0); 6326 STATIC_ASSERT(kInternalizedTag != 0);
6378 __ and_(tmp3, tmp1, Operand(tmp2)); 6327 __ and_(tmp3, tmp1, Operand(tmp2));
6379 __ tst(tmp3, Operand(kIsInternalizedMask)); 6328 __ tst(tmp3, Operand(kIsInternalizedMask));
6380 // Make sure r0 is non-zero. At this point input operands are 6329 // Make sure r0 is non-zero. At this point input operands are
6381 // guaranteed to be non-zero. 6330 // guaranteed to be non-zero.
6382 ASSERT(right.is(r0)); 6331 ASSERT(right.is(r0));
6383 __ Ret(ne); 6332 __ Ret(ne);
6384 } 6333 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
6550 __ b(eq, miss); 6499 __ b(eq, miss);
6551 6500
6552 Label good; 6501 Label good;
6553 __ cmp(entity_name, tmp); 6502 __ cmp(entity_name, tmp);
6554 __ b(eq, &good); 6503 __ b(eq, &good);
6555 6504
6556 // Check if the entry name is not a unique name. 6505 // Check if the entry name is not a unique name.
6557 __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); 6506 __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
6558 __ ldrb(entity_name, 6507 __ ldrb(entity_name,
6559 FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); 6508 FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
6560 __ tst(entity_name, Operand(kIsInternalizedMask)); 6509 __ JumpIfNotUniqueName(entity_name, miss);
6561 __ b(ne, &good);
6562 __ cmp(entity_name, Operand(SYMBOL_TYPE));
6563 __ b(ne, miss);
6564
6565 __ bind(&good); 6510 __ bind(&good);
6566 6511
6567 // Restore the properties. 6512 // Restore the properties.
6568 __ ldr(properties, 6513 __ ldr(properties,
6569 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 6514 FieldMemOperand(receiver, JSObject::kPropertiesOffset));
6570 } 6515 }
6571 6516
6572 const int spill_mask = 6517 const int spill_mask =
6573 (lr.bit() | r6.bit() | r5.bit() | r4.bit() | r3.bit() | 6518 (lr.bit() | r6.bit() | r5.bit() | r4.bit() | r3.bit() |
6574 r2.bit() | r1.bit() | r0.bit()); 6519 r2.bit() | r1.bit() | r0.bit());
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
6721 // Having undefined at this place means the name is not contained. 6666 // Having undefined at this place means the name is not contained.
6722 __ cmp(entry_key, Operand(undefined)); 6667 __ cmp(entry_key, Operand(undefined));
6723 __ b(eq, &not_in_dictionary); 6668 __ b(eq, &not_in_dictionary);
6724 6669
6725 // Stop if found the property. 6670 // Stop if found the property.
6726 __ cmp(entry_key, Operand(key)); 6671 __ cmp(entry_key, Operand(key));
6727 __ b(eq, &in_dictionary); 6672 __ b(eq, &in_dictionary);
6728 6673
6729 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { 6674 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
6730 // Check if the entry name is not a unique name. 6675 // Check if the entry name is not a unique name.
6731 Label cont;
6732 __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); 6676 __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
6733 __ ldrb(entry_key, 6677 __ ldrb(entry_key,
6734 FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); 6678 FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
6735 __ tst(entry_key, Operand(kIsInternalizedMask)); 6679 __ JumpIfNotUniqueName(entry_key, &maybe_in_dictionary);
6736 __ b(ne, &cont);
6737 __ cmp(entry_key, Operand(SYMBOL_TYPE));
6738 __ b(ne, &maybe_in_dictionary);
6739 __ bind(&cont);
6740 } 6680 }
6741 } 6681 }
6742 6682
6743 __ bind(&maybe_in_dictionary); 6683 __ bind(&maybe_in_dictionary);
6744 // If we are doing negative lookup then probing failure should be 6684 // If we are doing negative lookup then probing failure should be
6745 // treated as a lookup success. For positive lookup probing failure 6685 // treated as a lookup success. For positive lookup probing failure
6746 // should be treated as lookup failure. 6686 // should be treated as lookup failure.
6747 if (mode_ == POSITIVE_LOOKUP) { 6687 if (mode_ == POSITIVE_LOOKUP) {
6748 __ mov(result, Operand::Zero()); 6688 __ mov(result, Operand::Zero());
6749 __ Ret(); 6689 __ Ret();
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after
7334 Label okay_here; 7274 Label okay_here;
7335 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); 7275 Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
7336 __ cmp(r2, Operand(undefined_sentinel)); 7276 __ cmp(r2, Operand(undefined_sentinel));
7337 __ b(eq, &okay_here); 7277 __ b(eq, &okay_here);
7338 __ ldr(r3, FieldMemOperand(r2, 0)); 7278 __ ldr(r3, FieldMemOperand(r2, 0));
7339 __ cmp(r3, Operand(cell_map)); 7279 __ cmp(r3, Operand(cell_map));
7340 __ Assert(eq, "Expected property cell in register ebx"); 7280 __ Assert(eq, "Expected property cell in register ebx");
7341 __ bind(&okay_here); 7281 __ bind(&okay_here);
7342 } 7282 }
7343 7283
7344 if (FLAG_optimize_constructed_arrays) { 7284 Label no_info, switch_ready;
7345 Label no_info, switch_ready; 7285 // Get the elements kind and case on that.
7346 // Get the elements kind and case on that. 7286 __ cmp(r2, Operand(undefined_sentinel));
7347 __ cmp(r2, Operand(undefined_sentinel)); 7287 __ b(eq, &no_info);
7348 __ b(eq, &no_info); 7288 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
7349 __ ldr(r3, FieldMemOperand(r2, PropertyCell::kValueOffset)); 7289 __ JumpIfNotSmi(r3, &no_info);
7350 __ JumpIfNotSmi(r3, &no_info); 7290 __ SmiUntag(r3);
7351 __ SmiUntag(r3); 7291 __ jmp(&switch_ready);
7352 __ jmp(&switch_ready); 7292 __ bind(&no_info);
7353 __ bind(&no_info); 7293 __ mov(r3, Operand(GetInitialFastElementsKind()));
7354 __ mov(r3, Operand(GetInitialFastElementsKind())); 7294 __ bind(&switch_ready);
7355 __ bind(&switch_ready);
7356 7295
7357 if (argument_count_ == ANY) { 7296 if (argument_count_ == ANY) {
7358 Label not_zero_case, not_one_case; 7297 Label not_zero_case, not_one_case;
7359 __ tst(r0, r0); 7298 __ tst(r0, r0);
7360 __ b(ne, &not_zero_case); 7299 __ b(ne, &not_zero_case);
7361 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); 7300 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
7362 7301
7363 __ bind(&not_zero_case); 7302 __ bind(&not_zero_case);
7364 __ cmp(r0, Operand(1)); 7303 __ cmp(r0, Operand(1));
7365 __ b(gt, &not_one_case); 7304 __ b(gt, &not_one_case);
7366 CreateArrayDispatchOneArgument(masm); 7305 CreateArrayDispatchOneArgument(masm);
7367 7306
7368 __ bind(&not_one_case); 7307 __ bind(&not_one_case);
7369 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); 7308 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7370 } else if (argument_count_ == NONE) { 7309 } else if (argument_count_ == NONE) {
7371 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); 7310 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
7372 } else if (argument_count_ == ONE) { 7311 } else if (argument_count_ == ONE) {
7373 CreateArrayDispatchOneArgument(masm); 7312 CreateArrayDispatchOneArgument(masm);
7374 } else if (argument_count_ == MORE_THAN_ONE) { 7313 } else if (argument_count_ == MORE_THAN_ONE) {
7375 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); 7314 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7376 } else {
7377 UNREACHABLE();
7378 }
7379 } else { 7315 } else {
7380 Label generic_constructor; 7316 UNREACHABLE();
7381 // Run the native code for the Array function called as a constructor.
7382 ArrayNativeCode(masm, &generic_constructor);
7383
7384 // Jump to the generic construct code in case the specialized code cannot
7385 // handle the construction.
7386 __ bind(&generic_constructor);
7387 Handle<Code> generic_construct_stub =
7388 masm->isolate()->builtins()->JSConstructStubGeneric();
7389 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
7390 } 7317 }
7391 } 7318 }
7392 7319
7393 7320
7394 void InternalArrayConstructorStub::GenerateCase( 7321 void InternalArrayConstructorStub::GenerateCase(
7395 MacroAssembler* masm, ElementsKind kind) { 7322 MacroAssembler* masm, ElementsKind kind) {
7396 Label not_zero_case, not_one_case; 7323 Label not_zero_case, not_one_case;
7397 Label normal_sequence; 7324 Label normal_sequence;
7398 7325
7399 __ tst(r0, r0); 7326 __ tst(r0, r0);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
7441 7368
7442 // Initial map for the builtin Array function should be a map. 7369 // Initial map for the builtin Array function should be a map.
7443 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 7370 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
7444 // Will both indicate a NULL and a Smi. 7371 // Will both indicate a NULL and a Smi.
7445 __ tst(r3, Operand(kSmiTagMask)); 7372 __ tst(r3, Operand(kSmiTagMask));
7446 __ Assert(ne, "Unexpected initial map for Array function"); 7373 __ Assert(ne, "Unexpected initial map for Array function");
7447 __ CompareObjectType(r3, r3, r4, MAP_TYPE); 7374 __ CompareObjectType(r3, r3, r4, MAP_TYPE);
7448 __ Assert(eq, "Unexpected initial map for Array function"); 7375 __ Assert(eq, "Unexpected initial map for Array function");
7449 } 7376 }
7450 7377
7451 if (FLAG_optimize_constructed_arrays) { 7378 // Figure out the right elements kind
7452 // Figure out the right elements kind 7379 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
7453 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 7380 // Load the map's "bit field 2" into |result|. We only need the first byte,
7381 // but the following bit field extraction takes care of that anyway.
7382 __ ldr(r3, FieldMemOperand(r3, Map::kBitField2Offset));
7383 // Retrieve elements_kind from bit field 2.
7384 __ Ubfx(r3, r3, Map::kElementsKindShift, Map::kElementsKindBitCount);
7454 7385
7455 // Load the map's "bit field 2" into |result|. We only need the first byte, 7386 if (FLAG_debug_code) {
7456 // but the following bit field extraction takes care of that anyway. 7387 Label done;
7457 __ ldr(r3, FieldMemOperand(r3, Map::kBitField2Offset)); 7388 __ cmp(r3, Operand(FAST_ELEMENTS));
7458 // Retrieve elements_kind from bit field 2. 7389 __ b(eq, &done);
7459 __ Ubfx(r3, r3, Map::kElementsKindShift, Map::kElementsKindBitCount); 7390 __ cmp(r3, Operand(FAST_HOLEY_ELEMENTS));
7391 __ Assert(eq,
7392 "Invalid ElementsKind for InternalArray or InternalPackedArray");
7393 __ bind(&done);
7394 }
7460 7395
7461 if (FLAG_debug_code) { 7396 Label fast_elements_case;
7462 Label done; 7397 __ cmp(r3, Operand(FAST_ELEMENTS));
7463 __ cmp(r3, Operand(FAST_ELEMENTS)); 7398 __ b(eq, &fast_elements_case);
7464 __ b(eq, &done); 7399 GenerateCase(masm, FAST_HOLEY_ELEMENTS);
7465 __ cmp(r3, Operand(FAST_HOLEY_ELEMENTS));
7466 __ Assert(eq,
7467 "Invalid ElementsKind for InternalArray or InternalPackedArray");
7468 __ bind(&done);
7469 }
7470 7400
7471 Label fast_elements_case; 7401 __ bind(&fast_elements_case);
7472 __ cmp(r3, Operand(FAST_ELEMENTS)); 7402 GenerateCase(masm, FAST_ELEMENTS);
7473 __ b(eq, &fast_elements_case);
7474 GenerateCase(masm, FAST_HOLEY_ELEMENTS);
7475
7476 __ bind(&fast_elements_case);
7477 GenerateCase(masm, FAST_ELEMENTS);
7478 } else {
7479 Label generic_constructor;
7480 // Run the native code for the Array function called as constructor.
7481 ArrayNativeCode(masm, &generic_constructor);
7482
7483 // Jump to the generic construct code in case the specialized code cannot
7484 // handle the construction.
7485 __ bind(&generic_constructor);
7486 Handle<Code> generic_construct_stub =
7487 masm->isolate()->builtins()->JSConstructStubGeneric();
7488 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
7489 }
7490 } 7403 }
7491 7404
7492 7405
7493 #undef __ 7406 #undef __
7494 7407
7495 } } // namespace v8::internal 7408 } } // namespace v8::internal
7496 7409
7497 #endif // V8_TARGET_ARCH_ARM 7410 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/builtins-arm.cc ('k') | src/arm/frames-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698