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

Side by Side Diff: src/a64/code-stubs-a64.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/a64/builtins-a64.cc ('k') | src/a64/frames-a64.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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 682
683 // See call site for description. 683 // See call site for description.
684 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 684 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
685 Register left, 685 Register left,
686 Register right, 686 Register right,
687 Register left_type, 687 Register left_type,
688 Register right_type, 688 Register right_type,
689 Register scratch) { 689 Register scratch) {
690 ASSERT(!AreAliased(left, right, left_type, right_type, scratch)); 690 ASSERT(!AreAliased(left, right, left_type, right_type, scratch));
691 691
692 if (masm->emit_debug_code()) {
693 // We assume that the arguments are not identical.
694 __ Cmp(left, right);
695 __ Assert(ne, "Expected non-identical objects.");
696 }
697
692 // If either operand is a JS object or an oddball value, then they are not 698 // If either operand is a JS object or an oddball value, then they are not
693 // equal since their pointers are different. 699 // equal since their pointers are different.
694 // There is no test for undetectability in strict equality. 700 // There is no test for undetectability in strict equality.
695 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); 701 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
696 Label right_non_object; 702 Label right_non_object;
697 703
698 __ Cmp(right_type, FIRST_SPEC_OBJECT_TYPE); 704 __ Cmp(right_type, FIRST_SPEC_OBJECT_TYPE);
699 __ B(lt, &right_non_object); 705 __ B(lt, &right_non_object);
700 706
701 // Return non-zero - x0 already contains a non-zero pointer. 707 // Return non-zero - x0 already contains a non-zero pointer.
702 ASSERT(left.is(x0) || right.is(x0)); 708 ASSERT(left.is(x0) || right.is(x0));
703 Label return_not_equal; 709 Label return_not_equal;
704 __ Bind(&return_not_equal); 710 __ Bind(&return_not_equal);
705 __ Ret(); 711 __ Ret();
706 712
707 __ Bind(&right_non_object); 713 __ Bind(&right_non_object);
708 714
709 // Check for oddballs: true, false, null, undefined. 715 // Check for oddballs: true, false, null, undefined.
710 __ Cmp(right_type, ODDBALL_TYPE); 716 __ Cmp(right_type, ODDBALL_TYPE);
711 717
712 // If right is not ODDBALL, test left. Otherwise, set eq condition. 718 // If right is not ODDBALL, test left. Otherwise, set eq condition.
713 __ Ccmp(left_type, ODDBALL_TYPE, ZFlag, ne); 719 __ Ccmp(left_type, ODDBALL_TYPE, ZFlag, ne);
714 720
715 // If right or left is not ODDBALL, test left >= FIRST_SPEC_OBJECT_TYPE. 721 // If right or left is not ODDBALL, test left >= FIRST_SPEC_OBJECT_TYPE.
716 // Otherwise, right or left is ODDBALL, so set a ge condition. 722 // Otherwise, right or left is ODDBALL, so set a ge condition.
717 __ Ccmp(left_type, FIRST_SPEC_OBJECT_TYPE, NVFlag, ne); 723 __ Ccmp(left_type, FIRST_SPEC_OBJECT_TYPE, NVFlag, ne);
718 724
719 __ B(ge, &return_not_equal); 725 __ B(ge, &return_not_equal);
720 726
721 // Check for internalized-internalized comparison. Ensure that no non-strings 727 // Internalized strings are unique, so they can only be equal if they are the
722 // have the internalized bit set. 728 // same object. We have already tested that case, so if left and right are
723 STATIC_ASSERT(LAST_TYPE < (kNotStringTag + kIsInternalizedMask)); 729 // both internalized strings, they cannot be equal.
724 STATIC_ASSERT(kInternalizedTag != 0); 730 __ And(scratch, right_type, kIsNotStringMask | kIsInternalizedMask);
725 __ And(scratch, right_type, left_type); 731 __ Cmp(scratch, kInternalizedTag | kStringTag);
726 __ Tbnz(scratch, MaskToBit(kIsInternalizedMask), &return_not_equal); 732 __ And(scratch, left_type, kIsNotStringMask | kIsInternalizedMask);
733 __ Ccmp(scratch, kInternalizedTag | kStringTag, NoFlag, eq);
734 __ B(eq, &return_not_equal);
727 } 735 }
728 736
729 737
730 // See call site for description. 738 // See call site for description.
731 static void EmitSmiNonsmiComparison(MacroAssembler* masm, 739 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
732 Register left, 740 Register left,
733 Register right, 741 Register right,
734 FPRegister left_d, 742 FPRegister left_d,
735 FPRegister right_d, 743 FPRegister right_d,
736 Register scratch, 744 Register scratch,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 Register right, 815 Register right,
808 Register left_map, 816 Register left_map,
809 Register right_map, 817 Register right_map,
810 Register left_type, 818 Register left_type,
811 Register right_type, 819 Register right_type,
812 Label* possible_strings, 820 Label* possible_strings,
813 Label* not_both_strings) { 821 Label* not_both_strings) {
814 ASSERT(!AreAliased(left, right, left_map, right_map, left_type, right_type)); 822 ASSERT(!AreAliased(left, right, left_map, right_map, left_type, right_type));
815 Register result = x0; 823 Register result = x0;
816 824
817 // Ensure that no non-strings have the internalized bit set.
818 Label object_test; 825 Label object_test;
819 STATIC_ASSERT(kStringTag == 0); 826 STATIC_ASSERT(kStringTag == 0);
820 STATIC_ASSERT(kInternalizedTag != 0); 827 STATIC_ASSERT(kInternalizedTag != 0);
821 // TODO(all): reexamine this branch sequence for optimisation wrt branch 828 // TODO(all): reexamine this branch sequence for optimisation wrt branch
822 // prediction. 829 // prediction.
823 __ Tbnz(right_type, MaskToBit(kIsNotStringMask), &object_test); 830 __ Tbnz(right_type, MaskToBit(kIsNotStringMask), &object_test);
824 __ Tbz(right_type, MaskToBit(kIsInternalizedMask), possible_strings); 831 __ Tbz(right_type, MaskToBit(kIsInternalizedMask), possible_strings);
825 __ Tbnz(left_type, MaskToBit(kIsNotStringMask), not_both_strings); 832 __ Tbnz(left_type, MaskToBit(kIsNotStringMask), not_both_strings);
826 __ Tbz(left_type, MaskToBit(kIsInternalizedMask), possible_strings); 833 __ Tbz(left_type, MaskToBit(kIsInternalizedMask), possible_strings);
827 834
(...skipping 919 matching lines...) Expand 10 before | Expand all | Expand 10 after
1747 } 1754 }
1748 1755
1749 __ Bind(&not_smis); 1756 __ Bind(&not_smis);
1750 } 1757 }
1751 1758
1752 1759
1753 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 1760 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
1754 ASM_LOCATION("BinaryOpStub::GenerateSmiStub"); 1761 ASM_LOCATION("BinaryOpStub::GenerateSmiStub");
1755 Label right_arg_changed, call_runtime; 1762 Label right_arg_changed, call_runtime;
1756 1763
1757 if ((op_ == Token::MOD) && has_fixed_right_arg_) { 1764 if ((op_ == Token::MOD) && encoded_right_arg_.has_value) {
1758 // It is guaranteed that the value will fit into a Smi, because if it 1765 // It is guaranteed that the value will fit into a Smi, because if it
1759 // didn't, we wouldn't be here, see BinaryOp_Patch. 1766 // didn't, we wouldn't be here, see BinaryOp_Patch.
1760 __ CompareAndBranch(x0, Operand(Smi::FromInt(fixed_right_arg_value())), ne, 1767 __ CompareAndBranch(x0, Operand(Smi::FromInt(fixed_right_arg_value())), ne,
1761 &right_arg_changed); 1768 &right_arg_changed);
1762 } 1769 }
1763 1770
1764 #ifdef DEBUG 1771 #ifdef DEBUG
1765 Register saved_left = x18; 1772 Register saved_left = x18;
1766 Register saved_right = x19; 1773 Register saved_right = x19;
1767 if (masm->emit_debug_code()) { 1774 if (masm->emit_debug_code()) {
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after
2493 2500
2494 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 2501 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
2495 // It is important that the following stubs are generated in this order 2502 // It is important that the following stubs are generated in this order
2496 // because pregenerated stubs can only call other pregenerated stubs. 2503 // because pregenerated stubs can only call other pregenerated stubs.
2497 // RecordWriteStub uses StoreBufferOverflowStub, which in turn uses 2504 // RecordWriteStub uses StoreBufferOverflowStub, which in turn uses
2498 // CEntryStub. 2505 // CEntryStub.
2499 CEntryStub::GenerateAheadOfTime(isolate); 2506 CEntryStub::GenerateAheadOfTime(isolate);
2500 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 2507 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2501 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 2508 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
2502 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); 2509 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate);
2503 2510 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
2504 if (FLAG_optimize_constructed_arrays) {
2505 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
2506 }
2507 } 2511 }
2508 2512
2509 2513
2510 void CodeStub::GenerateFPStubs(Isolate* isolate) { 2514 void CodeStub::GenerateFPStubs(Isolate* isolate) {
2511 // Floating-point code doesn't get special handling in A64, so there's 2515 // Floating-point code doesn't get special handling in A64, so there's
2512 // nothing to do here. 2516 // nothing to do here.
2513 USE(isolate); 2517 USE(isolate);
2514 } 2518 }
2515 2519
2516 2520
(...skipping 1935 matching lines...) Expand 10 before | Expand all | Expand 10 after
4452 4456
4453 __ Bind(&done); 4457 __ Bind(&done);
4454 __ Ret(); 4458 __ Ret();
4455 4459
4456 __ Bind(&slow); 4460 __ Bind(&slow);
4457 __ Push(length_smi, index_smi, input); 4461 __ Push(length_smi, index_smi, input);
4458 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); 4462 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1);
4459 } 4463 }
4460 4464
4461 4465
4462 // TODO(mcapewel): This code has been ported as part of the merge process, but
4463 // is currently untested.
4464 // TODO(jbramley): Don't use static registers here, but take them as arguments.
4465 static void GenerateRecordCallTargetNoArray(MacroAssembler* masm) {
4466 ASM_UNIMPLEMENTED_BREAK("Untested: GenerateRecordCallTargetNoArray");
4467 // Cache the called function in a global property cell. Cache states are
4468 // uninitialized, monomorphic (indicated by a JSFunction), and megamorphic.
4469 // x1 : the function to call
4470 // x2 : cache cell for the call target
4471 Label done;
4472
4473 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
4474 masm->isolate()->heap()->undefined_value());
4475 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()),
4476 masm->isolate()->heap()->the_hole_value());
4477
4478 // Load the cache state.
4479 __ Ldr(x3, FieldMemOperand(x2, Cell::kValueOffset));
4480
4481 // A monomorphic cache hit or an already megamorphic state: invoke the
4482 // function without changing the state.
4483 __ Cmp(x3, x1);
4484 __ B(eq, &done);
4485 __ JumpIfRoot(x3, Heap::kUndefinedValueRootIndex, &done);
4486
4487 // A monomorphic miss (i.e, here the cache is not uninitialized) goes
4488 // megamorphic. MegamorphicSentinal is an immortal immovable object
4489 // (undefined) so no write-barrier is needed.
4490 Label skip_undef_store;
4491 __ JumpIfRoot(x3, Heap::kTheHoleValueRootIndex, &skip_undef_store);
4492 __ LoadRoot(ip0, Heap::kUndefinedValueRootIndex);
4493 __ Str(ip0, FieldMemOperand(x2, Cell::kValueOffset));
4494 __ B(&done);
4495 __ Bind(&skip_undef_store);
4496
4497 // An uninitialized cache is patched with the function.
4498 __ Str(x1, FieldMemOperand(x2, Cell::kValueOffset));
4499 // No need for a write barrier here - cells are rescanned.
4500
4501 __ Bind(&done);
4502 }
4503
4504
4505 // TODO(jbramley): Don't use static registers here, but take them as arguments. 4466 // TODO(jbramley): Don't use static registers here, but take them as arguments.
4506 static void GenerateRecordCallTarget(MacroAssembler* masm) { 4467 static void GenerateRecordCallTarget(MacroAssembler* masm) {
4507 // Cache the called function in a global property cell. Cache states are 4468 // Cache the called function in a global property cell. Cache states are
4508 // uninitialized, monomorphic (indicated by a JSFunction), and megamorphic. 4469 // uninitialized, monomorphic (indicated by a JSFunction), and megamorphic.
4509 // x1 : the function to call 4470 // x1 : the function to call
4510 // x2 : cache cell for the call target 4471 // x2 : cache cell for the call target
4511 ASSERT(FLAG_optimize_constructed_arrays);
4512 Label initialize, done, miss, megamorphic, not_array_function; 4472 Label initialize, done, miss, megamorphic, not_array_function;
4513 4473
4514 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), 4474 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
4515 masm->isolate()->heap()->undefined_value()); 4475 masm->isolate()->heap()->undefined_value());
4516 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), 4476 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()),
4517 masm->isolate()->heap()->the_hole_value()); 4477 masm->isolate()->heap()->the_hole_value());
4518 4478
4519 // Load the cache state. 4479 // Load the cache state.
4520 __ Ldr(x3, FieldMemOperand(x2, Cell::kValueOffset)); 4480 __ Ldr(x3, FieldMemOperand(x2, Cell::kValueOffset));
4521 4481
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
4606 __ Bind(&call); 4566 __ Bind(&call);
4607 } 4567 }
4608 4568
4609 // Check that the function is really a JavaScript function. 4569 // Check that the function is really a JavaScript function.
4610 // x1 function pushed function (to be verified) 4570 // x1 function pushed function (to be verified)
4611 __ JumpIfSmi(function, &non_function); 4571 __ JumpIfSmi(function, &non_function);
4612 // Get the map of the function object. 4572 // Get the map of the function object.
4613 __ JumpIfNotObjectType(function, x10, x10, JS_FUNCTION_TYPE, &slow); 4573 __ JumpIfNotObjectType(function, x10, x10, JS_FUNCTION_TYPE, &slow);
4614 4574
4615 if (RecordCallTarget()) { 4575 if (RecordCallTarget()) {
4616 if (FLAG_optimize_constructed_arrays) { 4576 GenerateRecordCallTarget(masm);
4617 GenerateRecordCallTarget(masm);
4618 } else {
4619 GenerateRecordCallTargetNoArray(masm);
4620 }
4621 } 4577 }
4622 4578
4623 // Fast-case: Invoke the function now. 4579 // Fast-case: Invoke the function now.
4624 // x1 function pushed function 4580 // x1 function pushed function
4625 ParameterCount actual(argc_); 4581 ParameterCount actual(argc_);
4626 4582
4627 if (ReceiverMightBeImplicit()) { 4583 if (ReceiverMightBeImplicit()) {
4628 Label call_as_function; 4584 Label call_as_function;
4629 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &call_as_function); 4585 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &call_as_function);
4630 __ InvokeFunction(function, 4586 __ InvokeFunction(function,
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
4688 Label slow, non_function_call; 4644 Label slow, non_function_call;
4689 4645
4690 // Check that the function is not a smi. 4646 // Check that the function is not a smi.
4691 __ JumpIfSmi(function, &non_function_call); 4647 __ JumpIfSmi(function, &non_function_call);
4692 // Check that the function is a JSFunction. 4648 // Check that the function is a JSFunction.
4693 Register object_type = x10; 4649 Register object_type = x10;
4694 __ JumpIfNotObjectType(function, object_type, object_type, JS_FUNCTION_TYPE, 4650 __ JumpIfNotObjectType(function, object_type, object_type, JS_FUNCTION_TYPE,
4695 &slow); 4651 &slow);
4696 4652
4697 if (RecordCallTarget()) { 4653 if (RecordCallTarget()) {
4698 if (FLAG_optimize_constructed_arrays) { 4654 GenerateRecordCallTarget(masm);
4699 GenerateRecordCallTarget(masm);
4700 } else {
4701 GenerateRecordCallTargetNoArray(masm);
4702 }
4703 } 4655 }
4704 4656
4705 // Jump to the function-specific construct stub. 4657 // Jump to the function-specific construct stub.
4706 Register jump_reg = FLAG_optimize_constructed_arrays ? x3 : x2; 4658 Register jump_reg = x3;
4707 Register shared_func_info = jump_reg; 4659 Register shared_func_info = jump_reg;
4708 Register cons_stub = jump_reg; 4660 Register cons_stub = jump_reg;
4709 Register cons_stub_code = jump_reg; 4661 Register cons_stub_code = jump_reg;
4710 __ Ldr(shared_func_info, 4662 __ Ldr(shared_func_info,
4711 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); 4663 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
4712 __ Ldr(cons_stub, 4664 __ Ldr(cons_stub,
4713 FieldMemOperand(shared_func_info, 4665 FieldMemOperand(shared_func_info,
4714 SharedFunctionInfo::kConstructStubOffset)); 4666 SharedFunctionInfo::kConstructStubOffset));
4715 __ Add(cons_stub_code, cons_stub, Code::kHeaderSize - kHeapObjectTag); 4667 __ Add(cons_stub_code, cons_stub, Code::kHeaderSize - kHeapObjectTag);
4716 __ Br(cons_stub_code); 4668 __ Br(cons_stub_code);
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
4957 4909
4958 // Check that both operands are internalized strings. 4910 // Check that both operands are internalized strings.
4959 Register rhs_map = x10; 4911 Register rhs_map = x10;
4960 Register lhs_map = x11; 4912 Register lhs_map = x11;
4961 Register rhs_type = x10; 4913 Register rhs_type = x10;
4962 Register lhs_type = x11; 4914 Register lhs_type = x11;
4963 __ Ldr(lhs_map, FieldMemOperand(lhs, HeapObject::kMapOffset)); 4915 __ Ldr(lhs_map, FieldMemOperand(lhs, HeapObject::kMapOffset));
4964 __ Ldr(rhs_map, FieldMemOperand(rhs, HeapObject::kMapOffset)); 4916 __ Ldr(rhs_map, FieldMemOperand(rhs, HeapObject::kMapOffset));
4965 __ Ldrb(lhs_type, FieldMemOperand(lhs_map, Map::kInstanceTypeOffset)); 4917 __ Ldrb(lhs_type, FieldMemOperand(lhs_map, Map::kInstanceTypeOffset));
4966 __ Ldrb(rhs_type, FieldMemOperand(rhs_map, Map::kInstanceTypeOffset)); 4918 __ Ldrb(rhs_type, FieldMemOperand(rhs_map, Map::kInstanceTypeOffset));
4967 __ And(x10, lhs_type, rhs_type); 4919
4968 __ Tbz(x10, MaskToBit(kIsInternalizedMask), &miss); 4920 __ And(x12, rhs_type, kIsNotStringMask | kIsInternalizedMask);
4969 STATIC_ASSERT(kInternalizedTag != 0); 4921 __ And(x13, lhs_type, kIsNotStringMask | kIsInternalizedMask);
4922 __ Cmp(x12, kInternalizedTag | kStringTag);
4923 __ Ccmp(x13, kInternalizedTag | kStringTag, NoFlag, eq);
4924 __ B(ne, &miss);
4970 4925
4971 // Internalized strings are compared by identity. 4926 // Internalized strings are compared by identity.
4972 STATIC_ASSERT(EQUAL == 0); 4927 STATIC_ASSERT(EQUAL == 0);
4973 __ Cmp(lhs, rhs); 4928 __ Cmp(lhs, rhs);
4974 __ Cset(result, ne); 4929 __ Cset(result, ne);
4975 __ Ret(); 4930 __ Ret();
4976 4931
4977 __ Bind(&miss); 4932 __ Bind(&miss);
4978 GenerateMiss(masm); 4933 GenerateMiss(masm);
4979 } 4934 }
(...skipping 17 matching lines...) Expand all
4997 4952
4998 // Check that both operands are unique names. This leaves the instance 4953 // Check that both operands are unique names. This leaves the instance
4999 // types loaded in tmp1 and tmp2. 4954 // types loaded in tmp1 and tmp2.
5000 __ Ldr(x10, FieldMemOperand(lhs, HeapObject::kMapOffset)); 4955 __ Ldr(x10, FieldMemOperand(lhs, HeapObject::kMapOffset));
5001 __ Ldr(x11, FieldMemOperand(rhs, HeapObject::kMapOffset)); 4956 __ Ldr(x11, FieldMemOperand(rhs, HeapObject::kMapOffset));
5002 __ Ldrb(lhs_instance_type, FieldMemOperand(x10, Map::kInstanceTypeOffset)); 4957 __ Ldrb(lhs_instance_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
5003 __ Ldrb(rhs_instance_type, FieldMemOperand(x11, Map::kInstanceTypeOffset)); 4958 __ Ldrb(rhs_instance_type, FieldMemOperand(x11, Map::kInstanceTypeOffset));
5004 4959
5005 // To avoid a miss, each instance type should be either SYMBOL_TYPE or it 4960 // To avoid a miss, each instance type should be either SYMBOL_TYPE or it
5006 // should have kInternalizedTag set. 4961 // should have kInternalizedTag set.
5007 STATIC_ASSERT(kInternalizedTag != 0); 4962 __ JumpIfNotUniqueName(lhs_instance_type, &miss);
5008 __ Tst(lhs_instance_type, kIsInternalizedMask); 4963 __ JumpIfNotUniqueName(rhs_instance_type, &miss);
5009 __ Ccmp(lhs_instance_type, SYMBOL_TYPE, ZFlag, eq);
5010 __ B(ne, &miss);
5011
5012 __ Tst(rhs_instance_type, kIsInternalizedMask);
5013 __ Ccmp(rhs_instance_type, SYMBOL_TYPE, ZFlag, eq);
5014 __ B(ne, &miss);
5015 4964
5016 // Unique names are compared by identity. 4965 // Unique names are compared by identity.
5017 STATIC_ASSERT(EQUAL == 0); 4966 STATIC_ASSERT(EQUAL == 0);
5018 __ Cmp(lhs, rhs); 4967 __ Cmp(lhs, rhs);
5019 __ Cset(result, ne); 4968 __ Cset(result, ne);
5020 __ Ret(); 4969 __ Ret();
5021 4970
5022 __ Bind(&miss); 4971 __ Bind(&miss);
5023 GenerateMiss(masm); 4972 GenerateMiss(masm);
5024 } 4973 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
5056 Label not_equal; 5005 Label not_equal;
5057 __ Cmp(lhs, rhs); 5006 __ Cmp(lhs, rhs);
5058 __ B(ne, &not_equal); 5007 __ B(ne, &not_equal);
5059 __ Mov(result, EQUAL); 5008 __ Mov(result, EQUAL);
5060 __ Ret(); 5009 __ Ret();
5061 5010
5062 __ Bind(&not_equal); 5011 __ Bind(&not_equal);
5063 // Handle not identical strings 5012 // Handle not identical strings
5064 5013
5065 // Check that both strings are internalized strings. If they are, we're done 5014 // Check that both strings are internalized strings. If they are, we're done
5066 // because we already know they are not identical. 5015 // because we already know they are not identical. We know they are both
5016 // strings.
5067 if (equality) { 5017 if (equality) {
5068 ASSERT(GetCondition() == eq); 5018 ASSERT(GetCondition() == eq);
5069 STATIC_ASSERT(kInternalizedTag != 0); 5019 STATIC_ASSERT(kInternalizedTag != 0);
5070 Label not_internalized_strings; 5020 Label not_internalized_strings;
5071 __ And(x12, lhs_type, rhs_type); 5021 __ And(x12, lhs_type, rhs_type);
5072 __ Tbz(x12, MaskToBit(kIsInternalizedMask), &not_internalized_strings); 5022 __ Tbz(x12, MaskToBit(kIsInternalizedMask), &not_internalized_strings);
5073 // Result is in rhs (x0), and not EQUAL, as rhs is not a smi. 5023 // Result is in rhs (x0), and not EQUAL, as rhs is not a smi.
5074 __ Ret(); 5024 __ Ret();
5075 __ Bind(&not_internalized_strings); 5025 __ Bind(&not_internalized_strings);
5076 } 5026 }
(...skipping 1814 matching lines...) Expand 10 before | Expand all | Expand 10 after
6891 __ Cmp(entity_name, Operand(name)); 6841 __ Cmp(entity_name, Operand(name));
6892 __ B(eq, miss); 6842 __ B(eq, miss);
6893 6843
6894 Label good; 6844 Label good;
6895 __ JumpIfRoot(entity_name, Heap::kTheHoleValueRootIndex, &good); 6845 __ JumpIfRoot(entity_name, Heap::kTheHoleValueRootIndex, &good);
6896 6846
6897 // Check if the entry name is not a unique name. 6847 // Check if the entry name is not a unique name.
6898 __ Ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); 6848 __ Ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
6899 __ Ldrb(entity_name, 6849 __ Ldrb(entity_name,
6900 FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); 6850 FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
6901 __ TestAndBranchIfAnySet(entity_name, kIsInternalizedMask, &good); 6851 __ JumpIfNotUniqueName(entity_name, miss);
6902 __ CompareAndBranch(entity_name, SYMBOL_TYPE, ne, miss);
6903
6904 __ Bind(&good); 6852 __ Bind(&good);
6905 } 6853 }
6906 6854
6907 CPURegList spill_list(CPURegister::kRegister, kXRegSize, 0, 6); 6855 CPURegList spill_list(CPURegister::kRegister, kXRegSize, 0, 6);
6908 spill_list.Combine(lr); 6856 spill_list.Combine(lr);
6909 spill_list.Remove(scratch0); // Scratch registers don't need to be preserved. 6857 spill_list.Remove(scratch0); // Scratch registers don't need to be preserved.
6910 6858
6911 __ PushCPURegList(spill_list); 6859 __ PushCPURegList(spill_list);
6912 6860
6913 __ Ldr(x0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 6861 __ Ldr(x0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
6978 // Having undefined at this place means the name is not contained. 6926 // Having undefined at this place means the name is not contained.
6979 __ Cmp(entry_key, undefined); 6927 __ Cmp(entry_key, undefined);
6980 __ B(eq, &not_in_dictionary); 6928 __ B(eq, &not_in_dictionary);
6981 6929
6982 // Stop if found the property. 6930 // Stop if found the property.
6983 __ Cmp(entry_key, key); 6931 __ Cmp(entry_key, key);
6984 __ B(eq, &in_dictionary); 6932 __ B(eq, &in_dictionary);
6985 6933
6986 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { 6934 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
6987 // Check if the entry name is not a unique name. 6935 // Check if the entry name is not a unique name.
6988 Label cont;
6989 __ Ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); 6936 __ Ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
6990 __ Ldrb(entry_key, FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); 6937 __ Ldrb(entry_key, FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
6991 STATIC_ASSERT(kIsInternalizedMask != 0); 6938 __ JumpIfNotUniqueName(entry_key, &maybe_in_dictionary);
6992 __ Tbnz(entry_key, MaskToBit(kIsInternalizedMask), &cont);
6993 __ CompareAndBranch(entry_key, SYMBOL_TYPE, ne, &maybe_in_dictionary);
6994 __ Bind(&cont);
6995 } 6939 }
6996 } 6940 }
6997 6941
6998 __ Bind(&maybe_in_dictionary); 6942 __ Bind(&maybe_in_dictionary);
6999 // If we are doing negative lookup then probing failure should be 6943 // If we are doing negative lookup then probing failure should be
7000 // treated as a lookup success. For positive lookup, probing failure 6944 // treated as a lookup success. For positive lookup, probing failure
7001 // should be treated as lookup failure. 6945 // should be treated as lookup failure.
7002 if (mode_ == POSITIVE_LOOKUP) { 6946 if (mode_ == POSITIVE_LOOKUP) {
7003 __ Mov(result, 0); 6947 __ Mov(result, 0);
7004 __ Ret(); 6948 __ Ret();
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
7172 Label okay_here; 7116 Label okay_here;
7173 Handle<Map> cell_map(masm->isolate()->heap()->global_property_cell_map()); 7117 Handle<Map> cell_map(masm->isolate()->heap()->global_property_cell_map());
7174 __ CompareAndBranch(type_info_cell, Operand(undefined_sentinel), 7118 __ CompareAndBranch(type_info_cell, Operand(undefined_sentinel),
7175 eq, &okay_here); 7119 eq, &okay_here);
7176 __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kMapOffset)); 7120 __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kMapOffset));
7177 __ Cmp(x10, Operand(cell_map)); 7121 __ Cmp(x10, Operand(cell_map));
7178 __ Assert(eq, "Expected property cell in type_info_cell"); 7122 __ Assert(eq, "Expected property cell in type_info_cell");
7179 __ Bind(&okay_here); 7123 __ Bind(&okay_here);
7180 } 7124 }
7181 7125
7182 if (FLAG_optimize_constructed_arrays) { 7126 Register kind = x3;
7183 Register kind = x3; 7127 Label no_info, switch_ready;
7184 Label no_info, switch_ready; 7128 // Get the elements kind and case on that.
7185 // Get the elements kind and case on that. 7129 __ CompareAndBranch(type_info_cell, Operand(undefined_sentinel),
7186 __ CompareAndBranch(type_info_cell, Operand(undefined_sentinel), 7130 eq, &no_info);
7187 eq, &no_info); 7131 __ Ldr(kind, FieldMemOperand(type_info_cell, PropertyCell::kValueOffset));
7188 __ Ldr(kind, FieldMemOperand(type_info_cell, PropertyCell::kValueOffset)); 7132 __ JumpIfNotSmi(kind, &no_info);
7189 __ JumpIfNotSmi(kind, &no_info); 7133 __ SmiUntag(kind);
7190 __ SmiUntag(kind); 7134 __ B(&switch_ready);
7191 __ B(&switch_ready);
7192 7135
7193 __ Bind(&no_info); 7136 __ Bind(&no_info);
7194 __ Mov(kind, GetInitialFastElementsKind()); 7137 __ Mov(kind, GetInitialFastElementsKind());
7195 __ Bind(&switch_ready); 7138 __ Bind(&switch_ready);
7196 7139
7197 if (argument_count_ == ANY) { 7140 if (argument_count_ == ANY) {
7198 Label zero_case, n_case; 7141 Label zero_case, n_case;
7199 __ Cbz(argc, &zero_case); 7142 __ Cbz(argc, &zero_case);
7200 __ Cmp(argc, 1); 7143 __ Cmp(argc, 1);
7201 __ B(ne, &n_case); 7144 __ B(ne, &n_case);
7202 7145
7203 // One argument. 7146 // One argument.
7204 CreateArrayDispatchOneArgument(masm); 7147 CreateArrayDispatchOneArgument(masm);
7205 7148
7206 __ Bind(&zero_case); 7149 __ Bind(&zero_case);
7207 // No arguments. 7150 // No arguments.
7208 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); 7151 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
7209 7152
7210 __ Bind(&n_case); 7153 __ Bind(&n_case);
7211 // N arguments. 7154 // N arguments.
7212 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); 7155 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7213 7156
7214 } else if (argument_count_ == NONE) { 7157 } else if (argument_count_ == NONE) {
7215 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); 7158 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
7216 } else if (argument_count_ == ONE) { 7159 } else if (argument_count_ == ONE) {
7217 CreateArrayDispatchOneArgument(masm); 7160 CreateArrayDispatchOneArgument(masm);
7218 } else if (argument_count_ == MORE_THAN_ONE) { 7161 } else if (argument_count_ == MORE_THAN_ONE) {
7219 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); 7162 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7220 } else {
7221 UNREACHABLE();
7222 }
7223 } else { 7163 } else {
7224 Label generic_constructor; 7164 UNREACHABLE();
7225 // Run the native code for the Array function called as a constructor.
7226 ArrayNativeCode(masm, &generic_constructor);
7227
7228 // Jump to the generic construct code in case the specialized code cannot
7229 // handle the construction.
7230 __ Bind(&generic_constructor);
7231 Handle<Code> generic_construct_stub =
7232 masm->isolate()->builtins()->JSConstructStubGeneric();
7233 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
7234 } 7165 }
7235 } 7166 }
7236 7167
7237 7168
7238 void InternalArrayConstructorStub::GenerateCase( 7169 void InternalArrayConstructorStub::GenerateCase(
7239 MacroAssembler* masm, ElementsKind kind) { 7170 MacroAssembler* masm, ElementsKind kind) {
7240 Label zero_case, n_case; 7171 Label zero_case, n_case;
7241 Register argc = x0; 7172 Register argc = x0;
7242 7173
7243 __ Cbz(argc, &zero_case); 7174 __ Cbz(argc, &zero_case);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
7293 __ Ldr(x10, FieldMemOperand(constructor, 7224 __ Ldr(x10, FieldMemOperand(constructor,
7294 JSFunction::kPrototypeOrInitialMapOffset)); 7225 JSFunction::kPrototypeOrInitialMapOffset));
7295 // Will both indicate a NULL and a Smi. 7226 // Will both indicate a NULL and a Smi.
7296 __ JumpIfSmi(x10, &unexpected_map); 7227 __ JumpIfSmi(x10, &unexpected_map);
7297 __ JumpIfObjectType(x10, x10, x11, MAP_TYPE, &map_ok); 7228 __ JumpIfObjectType(x10, x10, x11, MAP_TYPE, &map_ok);
7298 __ Bind(&unexpected_map); 7229 __ Bind(&unexpected_map);
7299 __ Abort("Unexpected initial map for Array function"); 7230 __ Abort("Unexpected initial map for Array function");
7300 __ Bind(&map_ok); 7231 __ Bind(&map_ok);
7301 } 7232 }
7302 7233
7303 if (FLAG_optimize_constructed_arrays) { 7234 Register kind = w3;
7304 Register kind = w3; 7235 // Figure out the right elements kind
7305 // Figure out the right elements kind 7236 __ Ldr(x10, FieldMemOperand(constructor,
7306 __ Ldr(x10, FieldMemOperand(constructor, 7237 JSFunction::kPrototypeOrInitialMapOffset));
7307 JSFunction::kPrototypeOrInitialMapOffset));
7308 7238
7309 // TODO(jbramley): Add a helper function to read elements kind from an 7239 // TODO(jbramley): Add a helper function to read elements kind from an
7310 // existing map. 7240 // existing map.
7311 // Load the map's "bit field 2" into result. 7241 // Load the map's "bit field 2" into result.
7312 __ Ldr(kind, FieldMemOperand(x10, Map::kBitField2Offset)); 7242 __ Ldr(kind, FieldMemOperand(x10, Map::kBitField2Offset));
7313 // Retrieve elements_kind from bit field 2. 7243 // Retrieve elements_kind from bit field 2.
7314 __ Ubfx(kind, kind, Map::kElementsKindShift, Map::kElementsKindBitCount); 7244 __ Ubfx(kind, kind, Map::kElementsKindShift, Map::kElementsKindBitCount);
7315 7245
7316 if (FLAG_debug_code) { 7246 if (FLAG_debug_code) {
7317 Label done; 7247 Label done;
7318 __ Cmp(x3, FAST_ELEMENTS); 7248 __ Cmp(x3, FAST_ELEMENTS);
7319 __ Ccmp(x3, FAST_HOLEY_ELEMENTS, ZFlag, ne); 7249 __ Ccmp(x3, FAST_HOLEY_ELEMENTS, ZFlag, ne);
7320 __ Assert(eq, 7250 __ Assert(eq,
7321 "Invalid ElementsKind for InternalArray or InternalPackedArray"); 7251 "Invalid ElementsKind for InternalArray or InternalPackedArray");
7322 } 7252 }
7323 7253
7324 Label fast_elements_case; 7254 Label fast_elements_case;
7325 __ CompareAndBranch(kind, FAST_ELEMENTS, eq, &fast_elements_case); 7255 __ CompareAndBranch(kind, FAST_ELEMENTS, eq, &fast_elements_case);
7326 GenerateCase(masm, FAST_HOLEY_ELEMENTS); 7256 GenerateCase(masm, FAST_HOLEY_ELEMENTS);
7327 7257
7328 __ Bind(&fast_elements_case); 7258 __ Bind(&fast_elements_case);
7329 GenerateCase(masm, FAST_ELEMENTS); 7259 GenerateCase(masm, FAST_ELEMENTS);
7330 } else {
7331 Label generic_constructor;
7332 // Run the native code for the Array function called as constructor.
7333 ArrayNativeCode(masm, &generic_constructor);
7334
7335 // Jump to the generic construct code in case the specialized code cannot
7336 // handle the construction.
7337 __ Bind(&generic_constructor);
7338 Handle<Code> generic_construct_stub =
7339 masm->isolate()->builtins()->JSConstructStubGeneric();
7340 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
7341 }
7342 } 7260 }
7343 7261
7344 7262
7345 #undef __ 7263 #undef __
7346 7264
7347 } } // namespace v8::internal 7265 } } // namespace v8::internal
7348 7266
7349 #endif // V8_TARGET_ARCH_A64 7267 #endif // V8_TARGET_ARCH_A64
OLDNEW
« no previous file with comments | « src/a64/builtins-a64.cc ('k') | src/a64/frames-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698