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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 6677076: Merge up to bleeding_edge r7201 to isolates branch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/isolates
Patch Set: Fix lint. Created 9 years, 9 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/x64/code-stubs-x64.cc ('k') | src/x64/full-codegen-x64.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 748 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 // The value to convert should be popped from the frame. 759 // The value to convert should be popped from the frame.
760 Result value = frame_->Pop(); 760 Result value = frame_->Pop();
761 value.ToRegister(); 761 value.ToRegister();
762 762
763 if (value.is_number()) { 763 if (value.is_number()) {
764 // Fast case if TypeInfo indicates only numbers. 764 // Fast case if TypeInfo indicates only numbers.
765 if (FLAG_debug_code) { 765 if (FLAG_debug_code) {
766 __ AbortIfNotNumber(value.reg()); 766 __ AbortIfNotNumber(value.reg());
767 } 767 }
768 // Smi => false iff zero. 768 // Smi => false iff zero.
769 __ SmiCompare(value.reg(), Smi::FromInt(0)); 769 __ Cmp(value.reg(), Smi::FromInt(0));
770 if (value.is_smi()) { 770 if (value.is_smi()) {
771 value.Unuse(); 771 value.Unuse();
772 dest->Split(not_zero); 772 dest->Split(not_zero);
773 } else { 773 } else {
774 dest->false_target()->Branch(equal); 774 dest->false_target()->Branch(equal);
775 Condition is_smi = masm_->CheckSmi(value.reg()); 775 Condition is_smi = masm_->CheckSmi(value.reg());
776 dest->true_target()->Branch(is_smi); 776 dest->true_target()->Branch(is_smi);
777 __ xorpd(xmm0, xmm0); 777 __ xorpd(xmm0, xmm0);
778 __ ucomisd(xmm0, FieldOperand(value.reg(), HeapNumber::kValueOffset)); 778 __ ucomisd(xmm0, FieldOperand(value.reg(), HeapNumber::kValueOffset));
779 value.Unuse(); 779 value.Unuse();
780 dest->Split(not_zero); 780 dest->Split(not_zero);
781 } 781 }
782 } else { 782 } else {
783 // Fast case checks. 783 // Fast case checks.
784 // 'false' => false. 784 // 'false' => false.
785 __ CompareRoot(value.reg(), Heap::kFalseValueRootIndex); 785 __ CompareRoot(value.reg(), Heap::kFalseValueRootIndex);
786 dest->false_target()->Branch(equal); 786 dest->false_target()->Branch(equal);
787 787
788 // 'true' => true. 788 // 'true' => true.
789 __ CompareRoot(value.reg(), Heap::kTrueValueRootIndex); 789 __ CompareRoot(value.reg(), Heap::kTrueValueRootIndex);
790 dest->true_target()->Branch(equal); 790 dest->true_target()->Branch(equal);
791 791
792 // 'undefined' => false. 792 // 'undefined' => false.
793 __ CompareRoot(value.reg(), Heap::kUndefinedValueRootIndex); 793 __ CompareRoot(value.reg(), Heap::kUndefinedValueRootIndex);
794 dest->false_target()->Branch(equal); 794 dest->false_target()->Branch(equal);
795 795
796 // Smi => false iff zero. 796 // Smi => false iff zero.
797 __ SmiCompare(value.reg(), Smi::FromInt(0)); 797 __ Cmp(value.reg(), Smi::FromInt(0));
798 dest->false_target()->Branch(equal); 798 dest->false_target()->Branch(equal);
799 Condition is_smi = masm_->CheckSmi(value.reg()); 799 Condition is_smi = masm_->CheckSmi(value.reg());
800 dest->true_target()->Branch(is_smi); 800 dest->true_target()->Branch(is_smi);
801 801
802 // Call the stub for all other cases. 802 // Call the stub for all other cases.
803 frame_->Push(&value); // Undo the Pop() from above. 803 frame_->Push(&value); // Undo the Pop() from above.
804 ToBooleanStub stub; 804 ToBooleanStub stub;
805 Result temp = frame_->CallStub(&stub, 1); 805 Result temp = frame_->CallStub(&stub, 1);
806 // Convert the result to a condition code. 806 // Convert the result to a condition code.
807 __ testq(temp.reg(), temp.reg()); 807 __ testq(temp.reg(), temp.reg());
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 operands_type); 1029 operands_type);
1030 answer = GenerateGenericBinaryOpStubCall(&stub, &left, &right); 1030 answer = GenerateGenericBinaryOpStubCall(&stub, &left, &right);
1031 } else if (right_is_smi_constant) { 1031 } else if (right_is_smi_constant) {
1032 answer = ConstantSmiBinaryOperation(expr, &left, right.handle(), 1032 answer = ConstantSmiBinaryOperation(expr, &left, right.handle(),
1033 false, overwrite_mode); 1033 false, overwrite_mode);
1034 } else if (left_is_smi_constant) { 1034 } else if (left_is_smi_constant) {
1035 answer = ConstantSmiBinaryOperation(expr, &right, left.handle(), 1035 answer = ConstantSmiBinaryOperation(expr, &right, left.handle(),
1036 true, overwrite_mode); 1036 true, overwrite_mode);
1037 } else { 1037 } else {
1038 // Set the flags based on the operation, type and loop nesting level. 1038 // Set the flags based on the operation, type and loop nesting level.
1039 // Bit operations always assume they likely operate on Smis. Still only 1039 // Bit operations always assume they likely operate on smis. Still only
1040 // generate the inline Smi check code if this operation is part of a loop. 1040 // generate the inline Smi check code if this operation is part of a loop.
1041 // For all other operations only inline the Smi check code for likely smis 1041 // For all other operations only inline the Smi check code for likely smis
1042 // if the operation is part of a loop. 1042 // if the operation is part of a loop.
1043 if (loop_nesting() > 0 && 1043 if (loop_nesting() > 0 &&
1044 (Token::IsBitOp(op) || 1044 (Token::IsBitOp(op) ||
1045 operands_type.IsInteger32() || 1045 operands_type.IsInteger32() ||
1046 expr->type()->IsLikelySmi())) { 1046 expr->type()->IsLikelySmi())) {
1047 answer = LikelySmiBinaryOperation(expr, &left, &right, overwrite_mode); 1047 answer = LikelySmiBinaryOperation(expr, &left, &right, overwrite_mode);
1048 } else { 1048 } else {
1049 GenericBinaryOpStub stub(op, 1049 GenericBinaryOpStub stub(op,
(...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after
2101 is_string.Bind(&left_side); 2101 is_string.Bind(&left_side);
2102 // left_side is a sequential ASCII string. 2102 // left_side is a sequential ASCII string.
2103 ASSERT(left_side.reg().is(left_reg)); 2103 ASSERT(left_side.reg().is(left_reg));
2104 right_side = Result(right_val); 2104 right_side = Result(right_val);
2105 Result temp2 = allocator_->Allocate(); 2105 Result temp2 = allocator_->Allocate();
2106 ASSERT(temp2.is_valid()); 2106 ASSERT(temp2.is_valid());
2107 // Test string equality and comparison. 2107 // Test string equality and comparison.
2108 if (cc == equal) { 2108 if (cc == equal) {
2109 Label comparison_done; 2109 Label comparison_done;
2110 __ SmiCompare(FieldOperand(left_side.reg(), String::kLengthOffset), 2110 __ SmiCompare(FieldOperand(left_side.reg(), String::kLengthOffset),
2111 Smi::FromInt(1)); 2111 Smi::FromInt(1));
2112 __ j(not_equal, &comparison_done); 2112 __ j(not_equal, &comparison_done);
2113 uint8_t char_value = 2113 uint8_t char_value =
2114 static_cast<uint8_t>(String::cast(*right_val)->Get(0)); 2114 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
2115 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize), 2115 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
2116 Immediate(char_value)); 2116 Immediate(char_value));
2117 __ bind(&comparison_done); 2117 __ bind(&comparison_done);
2118 } else { 2118 } else {
2119 __ movq(temp2.reg(), 2119 __ movq(temp2.reg(),
2120 FieldOperand(left_side.reg(), String::kLengthOffset)); 2120 FieldOperand(left_side.reg(), String::kLengthOffset));
2121 __ SmiSubConstant(temp2.reg(), temp2.reg(), Smi::FromInt(1)); 2121 __ SmiSubConstant(temp2.reg(), temp2.reg(), Smi::FromInt(1));
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
2287 // Since one side is a constant Smi, conversion order does not matter. 2287 // Since one side is a constant Smi, conversion order does not matter.
2288 if (left_side_constant_smi) { 2288 if (left_side_constant_smi) {
2289 Result* temp = left_side; 2289 Result* temp = left_side;
2290 left_side = right_side; 2290 left_side = right_side;
2291 right_side = temp; 2291 right_side = temp;
2292 cc = ReverseCondition(cc); 2292 cc = ReverseCondition(cc);
2293 // This may re-introduce greater or less_equal as the value of cc. 2293 // This may re-introduce greater or less_equal as the value of cc.
2294 // CompareStub and the inline code both support all values of cc. 2294 // CompareStub and the inline code both support all values of cc.
2295 } 2295 }
2296 // Implement comparison against a constant Smi, inlining the case 2296 // Implement comparison against a constant Smi, inlining the case
2297 // where both sides are Smis. 2297 // where both sides are smis.
2298 left_side->ToRegister(); 2298 left_side->ToRegister();
2299 Register left_reg = left_side->reg(); 2299 Register left_reg = left_side->reg();
2300 Smi* constant_smi = Smi::cast(*right_side->handle()); 2300 Smi* constant_smi = Smi::cast(*right_side->handle());
2301 2301
2302 if (left_side->is_smi()) { 2302 if (left_side->is_smi()) {
2303 if (FLAG_debug_code) { 2303 if (FLAG_debug_code) {
2304 __ AbortIfNotSmi(left_reg); 2304 __ AbortIfNotSmi(left_reg);
2305 } 2305 }
2306 // Test smi equality and comparison by signed int comparison. 2306 // Test smi equality and comparison by signed int comparison.
2307 // Both sides are smis, so we can use an Immediate.
2308 __ SmiCompare(left_reg, constant_smi); 2307 __ SmiCompare(left_reg, constant_smi);
2309 left_side->Unuse(); 2308 left_side->Unuse();
2310 right_side->Unuse(); 2309 right_side->Unuse();
2311 dest->Split(cc); 2310 dest->Split(cc);
2312 } else { 2311 } else {
2313 // Only the case where the left side could possibly be a non-smi is left. 2312 // Only the case where the left side could possibly be a non-smi is left.
2314 JumpTarget is_smi; 2313 JumpTarget is_smi;
2315 if (cc == equal) { 2314 if (cc == equal) {
2316 // We can do the equality comparison before the smi check. 2315 // We can do the equality comparison before the smi check.
2317 __ SmiCompare(left_reg, constant_smi); 2316 __ Cmp(left_reg, constant_smi);
2318 dest->true_target()->Branch(equal); 2317 dest->true_target()->Branch(equal);
2319 Condition left_is_smi = masm_->CheckSmi(left_reg); 2318 Condition left_is_smi = masm_->CheckSmi(left_reg);
2320 dest->false_target()->Branch(left_is_smi); 2319 dest->false_target()->Branch(left_is_smi);
2321 } else { 2320 } else {
2322 // Do the smi check, then the comparison. 2321 // Do the smi check, then the comparison.
2323 Condition left_is_smi = masm_->CheckSmi(left_reg); 2322 Condition left_is_smi = masm_->CheckSmi(left_reg);
2324 is_smi.Branch(left_is_smi, left_side, right_side); 2323 is_smi.Branch(left_is_smi, left_side, right_side);
2325 } 2324 }
2326 2325
2327 // Jump or fall through to here if we are comparing a non-smi to a 2326 // Jump or fall through to here if we are comparing a non-smi to a
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
2569 __ movq(rdi, Operand(rsp, 2 * kPointerSize)); 2568 __ movq(rdi, Operand(rsp, 2 * kPointerSize));
2570 is_smi = masm_->CheckSmi(rdi); 2569 is_smi = masm_->CheckSmi(rdi);
2571 __ j(is_smi, &build_args); 2570 __ j(is_smi, &build_args);
2572 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 2571 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
2573 __ j(not_equal, &build_args); 2572 __ j(not_equal, &build_args);
2574 2573
2575 // Copy the arguments to this function possibly from the 2574 // Copy the arguments to this function possibly from the
2576 // adaptor frame below it. 2575 // adaptor frame below it.
2577 Label invoke, adapted; 2576 Label invoke, adapted;
2578 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2577 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2579 __ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset), 2578 __ Cmp(Operand(rdx, StandardFrameConstants::kContextOffset),
2580 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2579 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2581 __ j(equal, &adapted); 2580 __ j(equal, &adapted);
2582 2581
2583 // No arguments adaptor frame. Copy fixed number of arguments. 2582 // No arguments adaptor frame. Copy fixed number of arguments.
2584 __ Set(rax, scope()->num_parameters()); 2583 __ Set(rax, scope()->num_parameters());
2585 for (int i = 0; i < scope()->num_parameters(); i++) { 2584 for (int i = 0; i < scope()->num_parameters(); i++) {
2586 __ push(frame_->ParameterAt(i)); 2585 __ push(frame_->ParameterAt(i));
2587 } 2586 }
2588 __ jmp(&invoke); 2587 __ jmp(&invoke);
2589 2588
2590 // Arguments adaptor frame present. Copy arguments from there, but 2589 // Arguments adaptor frame present. Copy arguments from there, but
(...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after
3851 __ cmpq(rcx, rdx); 3850 __ cmpq(rcx, rdx);
3852 end_del_check.Branch(equal); 3851 end_del_check.Branch(equal);
3853 3852
3854 // Convert the entry to a string (or null if it isn't a property anymore). 3853 // Convert the entry to a string (or null if it isn't a property anymore).
3855 frame_->EmitPush(frame_->ElementAt(4)); // push enumerable 3854 frame_->EmitPush(frame_->ElementAt(4)); // push enumerable
3856 frame_->EmitPush(rbx); // push entry 3855 frame_->EmitPush(rbx); // push entry
3857 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2); 3856 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2);
3858 __ movq(rbx, rax); 3857 __ movq(rbx, rax);
3859 3858
3860 // If the property has been removed while iterating, we just skip it. 3859 // If the property has been removed while iterating, we just skip it.
3861 __ SmiCompare(rbx, Smi::FromInt(0)); 3860 __ Cmp(rbx, Smi::FromInt(0));
3862 node->continue_target()->Branch(equal); 3861 node->continue_target()->Branch(equal);
3863 3862
3864 end_del_check.Bind(); 3863 end_del_check.Bind();
3865 // Store the entry in the 'each' expression and take another spin in the 3864 // Store the entry in the 'each' expression and take another spin in the
3866 // loop. rdx: i'th entry of the enum cache (or string there of) 3865 // loop. rdx: i'th entry of the enum cache (or string there of)
3867 frame_->EmitPush(rbx); 3866 frame_->EmitPush(rbx);
3868 { Reference each(this, node->each()); 3867 { Reference each(this, node->each());
3869 // Loading a reference may leave the frame in an unspilled state. 3868 // Loading a reference may leave the frame in an unspilled state.
3870 frame_->SpillAll(); 3869 frame_->SpillAll();
3871 if (!each.is_illegal()) { 3870 if (!each.is_illegal()) {
(...skipping 2320 matching lines...) Expand 10 before | Expand all | Expand 10 after
6192 6191
6193 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { 6192 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
6194 ASSERT(args->length() == 0); 6193 ASSERT(args->length() == 0);
6195 6194
6196 // Get the frame pointer for the calling frame. 6195 // Get the frame pointer for the calling frame.
6197 Result fp = allocator()->Allocate(); 6196 Result fp = allocator()->Allocate();
6198 __ movq(fp.reg(), Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 6197 __ movq(fp.reg(), Operand(rbp, StandardFrameConstants::kCallerFPOffset));
6199 6198
6200 // Skip the arguments adaptor frame if it exists. 6199 // Skip the arguments adaptor frame if it exists.
6201 Label check_frame_marker; 6200 Label check_frame_marker;
6202 __ SmiCompare(Operand(fp.reg(), StandardFrameConstants::kContextOffset), 6201 __ Cmp(Operand(fp.reg(), StandardFrameConstants::kContextOffset),
6203 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 6202 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
6204 __ j(not_equal, &check_frame_marker); 6203 __ j(not_equal, &check_frame_marker);
6205 __ movq(fp.reg(), Operand(fp.reg(), StandardFrameConstants::kCallerFPOffset)); 6204 __ movq(fp.reg(), Operand(fp.reg(), StandardFrameConstants::kCallerFPOffset));
6206 6205
6207 // Check the marker in the calling frame. 6206 // Check the marker in the calling frame.
6208 __ bind(&check_frame_marker); 6207 __ bind(&check_frame_marker);
6209 __ SmiCompare(Operand(fp.reg(), StandardFrameConstants::kMarkerOffset), 6208 __ Cmp(Operand(fp.reg(), StandardFrameConstants::kMarkerOffset),
6210 Smi::FromInt(StackFrame::CONSTRUCT)); 6209 Smi::FromInt(StackFrame::CONSTRUCT));
6211 fp.Unuse(); 6210 fp.Unuse();
6212 destination()->Split(equal); 6211 destination()->Split(equal);
6213 } 6212 }
6214 6213
6215 6214
6216 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 6215 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
6217 ASSERT(args->length() == 0); 6216 ASSERT(args->length() == 0);
6218 6217
6219 Result fp = allocator_->Allocate(); 6218 Result fp = allocator_->Allocate();
6220 Result result = allocator_->Allocate(); 6219 Result result = allocator_->Allocate();
6221 ASSERT(fp.is_valid() && result.is_valid()); 6220 ASSERT(fp.is_valid() && result.is_valid());
6222 6221
6223 Label exit; 6222 Label exit;
6224 6223
6225 // Get the number of formal parameters. 6224 // Get the number of formal parameters.
6226 __ Move(result.reg(), Smi::FromInt(scope()->num_parameters())); 6225 __ Move(result.reg(), Smi::FromInt(scope()->num_parameters()));
6227 6226
6228 // Check if the calling frame is an arguments adaptor frame. 6227 // Check if the calling frame is an arguments adaptor frame.
6229 __ movq(fp.reg(), Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 6228 __ movq(fp.reg(), Operand(rbp, StandardFrameConstants::kCallerFPOffset));
6230 __ SmiCompare(Operand(fp.reg(), StandardFrameConstants::kContextOffset), 6229 __ Cmp(Operand(fp.reg(), StandardFrameConstants::kContextOffset),
6231 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 6230 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
6232 __ j(not_equal, &exit); 6231 __ j(not_equal, &exit);
6233 6232
6234 // Arguments adaptor case: Read the arguments length from the 6233 // Arguments adaptor case: Read the arguments length from the
6235 // adaptor frame. 6234 // adaptor frame.
6236 __ movq(result.reg(), 6235 __ movq(result.reg(),
6237 Operand(fp.reg(), ArgumentsAdaptorFrameConstants::kLengthOffset)); 6236 Operand(fp.reg(), ArgumentsAdaptorFrameConstants::kLengthOffset));
6238 6237
6239 __ bind(&exit); 6238 __ bind(&exit);
6240 result.set_type_info(TypeInfo::Smi()); 6239 result.set_type_info(TypeInfo::Smi());
6241 if (FLAG_debug_code) { 6240 if (FLAG_debug_code) {
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
6777 frame_->Spill(index1.reg()); 6776 frame_->Spill(index1.reg());
6778 frame_->Spill(index2.reg()); 6777 frame_->Spill(index2.reg());
6779 6778
6780 DeferredSwapElements* deferred = new DeferredSwapElements(object.reg(), 6779 DeferredSwapElements* deferred = new DeferredSwapElements(object.reg(),
6781 index1.reg(), 6780 index1.reg(),
6782 index2.reg()); 6781 index2.reg());
6783 6782
6784 // Fetch the map and check if array is in fast case. 6783 // Fetch the map and check if array is in fast case.
6785 // Check that object doesn't require security checks and 6784 // Check that object doesn't require security checks and
6786 // has no indexed interceptor. 6785 // has no indexed interceptor.
6787 __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg()); 6786 __ CmpObjectType(object.reg(), JS_ARRAY_TYPE, tmp1.reg());
6788 deferred->Branch(below); 6787 deferred->Branch(not_equal);
6789 __ testb(FieldOperand(tmp1.reg(), Map::kBitFieldOffset), 6788 __ testb(FieldOperand(tmp1.reg(), Map::kBitFieldOffset),
6790 Immediate(KeyedLoadIC::kSlowCaseBitFieldMask)); 6789 Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
6791 deferred->Branch(not_zero); 6790 deferred->Branch(not_zero);
6792 6791
6793 // Check the object's elements are in fast case and writable. 6792 // Check the object's elements are in fast case and writable.
6794 __ movq(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset)); 6793 __ movq(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset));
6795 __ CompareRoot(FieldOperand(tmp1.reg(), HeapObject::kMapOffset), 6794 __ CompareRoot(FieldOperand(tmp1.reg(), HeapObject::kMapOffset),
6796 Heap::kFixedArrayMapRootIndex); 6795 Heap::kFixedArrayMapRootIndex);
6797 deferred->Branch(not_equal); 6796 deferred->Branch(not_equal);
6798 6797
(...skipping 21 matching lines...) Expand all
6820 FixedArray::kHeaderSize)); 6819 FixedArray::kHeaderSize));
6821 6820
6822 // Swap elements. 6821 // Swap elements.
6823 __ movq(object.reg(), Operand(index1.reg(), 0)); 6822 __ movq(object.reg(), Operand(index1.reg(), 0));
6824 __ movq(tmp2.reg(), Operand(index2.reg(), 0)); 6823 __ movq(tmp2.reg(), Operand(index2.reg(), 0));
6825 __ movq(Operand(index2.reg(), 0), object.reg()); 6824 __ movq(Operand(index2.reg(), 0), object.reg());
6826 __ movq(Operand(index1.reg(), 0), tmp2.reg()); 6825 __ movq(Operand(index1.reg(), 0), tmp2.reg());
6827 6826
6828 Label done; 6827 Label done;
6829 __ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done); 6828 __ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done);
6830 // Possible optimization: do a check that both values are Smis 6829 // Possible optimization: do a check that both values are smis
6831 // (or them and test against Smi mask.) 6830 // (or them and test against Smi mask.)
6832 6831
6833 __ movq(tmp2.reg(), tmp1.reg()); 6832 __ movq(tmp2.reg(), tmp1.reg());
6834 __ RecordWriteHelper(tmp1.reg(), index1.reg(), object.reg()); 6833 __ RecordWriteHelper(tmp1.reg(), index1.reg(), object.reg());
6835 __ RecordWriteHelper(tmp2.reg(), index2.reg(), object.reg()); 6834 __ RecordWriteHelper(tmp2.reg(), index2.reg(), object.reg());
6836 __ bind(&done); 6835 __ bind(&done);
6837 6836
6838 deferred->BindExit(); 6837 deferred->BindExit();
6839 frame_->Push(FACTORY->undefined_value()); 6838 frame_->Push(FACTORY->undefined_value());
6840 } 6839 }
(...skipping 1671 matching lines...) Expand 10 before | Expand all | Expand 10 after
8512 if (!key.is_smi()) { 8511 if (!key.is_smi()) {
8513 __ JumpIfNotSmi(key.reg(), deferred->entry_label()); 8512 __ JumpIfNotSmi(key.reg(), deferred->entry_label());
8514 } else if (FLAG_debug_code) { 8513 } else if (FLAG_debug_code) {
8515 __ AbortIfNotSmi(key.reg()); 8514 __ AbortIfNotSmi(key.reg());
8516 } 8515 }
8517 8516
8518 // Check that the receiver is a JSArray. 8517 // Check that the receiver is a JSArray.
8519 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister); 8518 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister);
8520 deferred->Branch(not_equal); 8519 deferred->Branch(not_equal);
8521 8520
8522 // Check that the key is within bounds. Both the key and the length of
8523 // the JSArray are smis. Use unsigned comparison to handle negative keys.
8524 __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset),
8525 key.reg());
8526 deferred->Branch(below_equal);
8527
8528 // Get the elements array from the receiver and check that it is not a 8521 // Get the elements array from the receiver and check that it is not a
8529 // dictionary. 8522 // dictionary.
8530 __ movq(tmp.reg(), 8523 __ movq(tmp.reg(),
8531 FieldOperand(receiver.reg(), JSArray::kElementsOffset)); 8524 FieldOperand(receiver.reg(), JSArray::kElementsOffset));
8532 8525
8533 // Check whether it is possible to omit the write barrier. If the elements 8526 // Check whether it is possible to omit the write barrier. If the elements
8534 // array is in new space or the value written is a smi we can safely update 8527 // array is in new space or the value written is a smi we can safely update
8535 // the elements array without write barrier. 8528 // the elements array without write barrier.
8536 Label in_new_space; 8529 Label in_new_space;
8537 __ InNewSpace(tmp.reg(), tmp2.reg(), equal, &in_new_space); 8530 __ InNewSpace(tmp.reg(), tmp2.reg(), equal, &in_new_space);
8538 if (!value_is_constant) { 8531 if (!value_is_constant) {
8539 __ JumpIfNotSmi(result.reg(), deferred->entry_label()); 8532 __ JumpIfNotSmi(result.reg(), deferred->entry_label());
8540 } 8533 }
8541 8534
8542 __ bind(&in_new_space); 8535 __ bind(&in_new_space);
8543 // Bind the deferred code patch site to be able to locate the fixed 8536 // Bind the deferred code patch site to be able to locate the fixed
8544 // array map comparison. When debugging, we patch this comparison to 8537 // array map comparison. When debugging, we patch this comparison to
8545 // always fail so that we will hit the IC call in the deferred code 8538 // always fail so that we will hit the IC call in the deferred code
8546 // which will allow the debugger to break for fast case stores. 8539 // which will allow the debugger to break for fast case stores.
8547 __ bind(deferred->patch_site()); 8540 __ bind(deferred->patch_site());
8548 // Avoid using __ to ensure the distance from patch_site 8541 // Avoid using __ to ensure the distance from patch_site
8549 // to the map address is always the same. 8542 // to the map address is always the same.
8550 masm()->movq(kScratchRegister, FACTORY->fixed_array_map(), 8543 masm()->movq(kScratchRegister, FACTORY->fixed_array_map(),
8551 RelocInfo::EMBEDDED_OBJECT); 8544 RelocInfo::EMBEDDED_OBJECT);
8552 __ cmpq(FieldOperand(tmp.reg(), HeapObject::kMapOffset), 8545 __ cmpq(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
8553 kScratchRegister); 8546 kScratchRegister);
8554 deferred->Branch(not_equal); 8547 deferred->Branch(not_equal);
8555 8548
8549 // Check that the key is within bounds. Both the key and the length of
8550 // the JSArray are smis (because the fixed array check above ensures the
8551 // elements are in fast case). Use unsigned comparison to handle negative
8552 // keys.
8553 __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset),
8554 key.reg());
8555 deferred->Branch(below_equal);
8556
8556 // Store the value. 8557 // Store the value.
8557 SmiIndex index = 8558 SmiIndex index =
8558 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); 8559 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2);
8559 __ movq(FieldOperand(tmp.reg(), 8560 __ movq(FieldOperand(tmp.reg(),
8560 index.reg, 8561 index.reg,
8561 index.scale, 8562 index.scale,
8562 FixedArray::kHeaderSize), 8563 FixedArray::kHeaderSize),
8563 result.reg()); 8564 result.reg());
8564 __ IncrementCounter(COUNTERS->keyed_store_inline(), 1); 8565 __ IncrementCounter(COUNTERS->keyed_store_inline(), 1);
8565 8566
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
8837 } 8838 }
8838 8839
8839 #endif 8840 #endif
8840 8841
8841 8842
8842 #undef __ 8843 #undef __
8843 8844
8844 } } // namespace v8::internal 8845 } } // namespace v8::internal
8845 8846
8846 #endif // V8_TARGET_ARCH_X64 8847 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.cc ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698