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

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

Issue 6529032: Merge 6168:6800 from bleeding_edge to experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 731 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 : LAZY_ARGUMENTS_ALLOCATION; 742 : LAZY_ARGUMENTS_ALLOCATION;
743 } 743 }
744 744
745 745
746 Result CodeGenerator::StoreArgumentsObject(bool initial) { 746 Result CodeGenerator::StoreArgumentsObject(bool initial) {
747 ArgumentsAllocationMode mode = ArgumentsMode(); 747 ArgumentsAllocationMode mode = ArgumentsMode();
748 ASSERT(mode != NO_ARGUMENTS_ALLOCATION); 748 ASSERT(mode != NO_ARGUMENTS_ALLOCATION);
749 749
750 Comment cmnt(masm_, "[ store arguments object"); 750 Comment cmnt(masm_, "[ store arguments object");
751 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) { 751 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) {
752 // When using lazy arguments allocation, we store the hole value 752 // When using lazy arguments allocation, we store the arguments marker value
753 // as a sentinel indicating that the arguments object hasn't been 753 // as a sentinel indicating that the arguments object hasn't been
754 // allocated yet. 754 // allocated yet.
755 frame_->Push(Factory::the_hole_value()); 755 frame_->Push(Factory::arguments_marker());
756 } else { 756 } else {
757 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 757 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
758 frame_->PushFunction(); 758 frame_->PushFunction();
759 frame_->PushReceiverSlotAddress(); 759 frame_->PushReceiverSlotAddress();
760 frame_->Push(Smi::FromInt(scope()->num_parameters())); 760 frame_->Push(Smi::FromInt(scope()->num_parameters()));
761 Result result = frame_->CallStub(&stub, 3); 761 Result result = frame_->CallStub(&stub, 3);
762 frame_->Push(&result); 762 frame_->Push(&result);
763 } 763 }
764 764
765 Variable* arguments = scope()->arguments(); 765 Variable* arguments = scope()->arguments();
766 Variable* shadow = scope()->arguments_shadow(); 766 Variable* shadow = scope()->arguments_shadow();
767 ASSERT(arguments != NULL && arguments->AsSlot() != NULL); 767 ASSERT(arguments != NULL && arguments->AsSlot() != NULL);
768 ASSERT(shadow != NULL && shadow->AsSlot() != NULL); 768 ASSERT(shadow != NULL && shadow->AsSlot() != NULL);
769 JumpTarget done; 769 JumpTarget done;
770 bool skip_arguments = false; 770 bool skip_arguments = false;
771 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { 771 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
772 // We have to skip storing into the arguments slot if it has 772 // We have to skip storing into the arguments slot if it has
773 // already been written to. This can happen if the a function 773 // already been written to. This can happen if the a function
774 // has a local variable named 'arguments'. 774 // has a local variable named 'arguments'.
775 LoadFromSlot(arguments->AsSlot(), NOT_INSIDE_TYPEOF); 775 LoadFromSlot(arguments->AsSlot(), NOT_INSIDE_TYPEOF);
776 Result probe = frame_->Pop(); 776 Result probe = frame_->Pop();
777 if (probe.is_constant()) { 777 if (probe.is_constant()) {
778 // We have to skip updating the arguments object if it has 778 // We have to skip updating the arguments object if it has
779 // been assigned a proper value. 779 // been assigned a proper value.
780 skip_arguments = !probe.handle()->IsTheHole(); 780 skip_arguments = !probe.handle()->IsArgumentsMarker();
781 } else { 781 } else {
782 __ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value())); 782 __ cmp(Operand(probe.reg()), Immediate(Factory::arguments_marker()));
783 probe.Unuse(); 783 probe.Unuse();
784 done.Branch(not_equal); 784 done.Branch(not_equal);
785 } 785 }
786 } 786 }
787 if (!skip_arguments) { 787 if (!skip_arguments) {
788 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT); 788 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT);
789 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); 789 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
790 } 790 }
791 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT); 791 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
792 return frame_->Pop(); 792 return frame_->Pop();
(...skipping 2498 matching lines...) Expand 10 before | Expand all | Expand 10 after
3291 // Check if the arguments object has been lazily allocated 3291 // Check if the arguments object has been lazily allocated
3292 // already. If so, just use that instead of copying the arguments 3292 // already. If so, just use that instead of copying the arguments
3293 // from the stack. This also deals with cases where a local variable 3293 // from the stack. This also deals with cases where a local variable
3294 // named 'arguments' has been introduced. 3294 // named 'arguments' has been introduced.
3295 frame_->Dup(); 3295 frame_->Dup();
3296 Result probe = frame_->Pop(); 3296 Result probe = frame_->Pop();
3297 { VirtualFrame::SpilledScope spilled_scope; 3297 { VirtualFrame::SpilledScope spilled_scope;
3298 Label slow, done; 3298 Label slow, done;
3299 bool try_lazy = true; 3299 bool try_lazy = true;
3300 if (probe.is_constant()) { 3300 if (probe.is_constant()) {
3301 try_lazy = probe.handle()->IsTheHole(); 3301 try_lazy = probe.handle()->IsArgumentsMarker();
3302 } else { 3302 } else {
3303 __ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value())); 3303 __ cmp(Operand(probe.reg()), Immediate(Factory::arguments_marker()));
3304 probe.Unuse(); 3304 probe.Unuse();
3305 __ j(not_equal, &slow); 3305 __ j(not_equal, &slow);
3306 } 3306 }
3307 3307
3308 if (try_lazy) { 3308 if (try_lazy) {
3309 Label build_args; 3309 Label build_args;
3310 // Get rid of the arguments object probe. 3310 // Get rid of the arguments object probe.
3311 frame_->Drop(); // Can be called on a spilled frame. 3311 frame_->Drop(); // Can be called on a spilled frame.
3312 // Stack now has 3 elements on it. 3312 // Stack now has 3 elements on it.
3313 // Contents of stack at this point: 3313 // Contents of stack at this point:
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
3768 3768
3769 // Add a label for checking the size of the code used for returning. 3769 // Add a label for checking the size of the code used for returning.
3770 #ifdef DEBUG 3770 #ifdef DEBUG
3771 Label check_exit_codesize; 3771 Label check_exit_codesize;
3772 masm_->bind(&check_exit_codesize); 3772 masm_->bind(&check_exit_codesize);
3773 #endif 3773 #endif
3774 3774
3775 // Leave the frame and return popping the arguments and the 3775 // Leave the frame and return popping the arguments and the
3776 // receiver. 3776 // receiver.
3777 frame_->Exit(); 3777 frame_->Exit();
3778 masm_->ret((scope()->num_parameters() + 1) * kPointerSize); 3778 int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize;
3779 __ Ret(arguments_bytes, ecx);
3779 DeleteFrame(); 3780 DeleteFrame();
3780 3781
3781 #ifdef ENABLE_DEBUGGER_SUPPORT 3782 #ifdef ENABLE_DEBUGGER_SUPPORT
3782 // Check that the size of the code used for returning matches what is 3783 // Check that the size of the code used for returning is large enough
3783 // expected by the debugger. 3784 // for the debugger's requirements.
3784 ASSERT_EQ(Assembler::kJSReturnSequenceLength, 3785 ASSERT(Assembler::kJSReturnSequenceLength <=
3785 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 3786 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
3786 #endif 3787 #endif
3787 } 3788 }
3788 3789
3789 3790
3790 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 3791 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
3791 ASSERT(!in_spilled_code()); 3792 ASSERT(!in_spilled_code());
3792 Comment cmnt(masm_, "[ WithEnterStatement"); 3793 Comment cmnt(masm_, "[ WithEnterStatement");
3793 CodeForStatementPosition(node); 3794 CodeForStatementPosition(node);
3794 Load(node->expression()); 3795 Load(node->expression());
3795 Result context; 3796 Result context;
(...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after
5065 // Bail out quickly if we're not using lazy arguments allocation. 5066 // Bail out quickly if we're not using lazy arguments allocation.
5066 if (ArgumentsMode() != LAZY_ARGUMENTS_ALLOCATION) return; 5067 if (ArgumentsMode() != LAZY_ARGUMENTS_ALLOCATION) return;
5067 5068
5068 // ... or if the slot isn't a non-parameter arguments slot. 5069 // ... or if the slot isn't a non-parameter arguments slot.
5069 if (slot->type() == Slot::PARAMETER || !slot->is_arguments()) return; 5070 if (slot->type() == Slot::PARAMETER || !slot->is_arguments()) return;
5070 5071
5071 // If the loaded value is a constant, we know if the arguments 5072 // If the loaded value is a constant, we know if the arguments
5072 // object has been lazily loaded yet. 5073 // object has been lazily loaded yet.
5073 Result result = frame()->Pop(); 5074 Result result = frame()->Pop();
5074 if (result.is_constant()) { 5075 if (result.is_constant()) {
5075 if (result.handle()->IsTheHole()) { 5076 if (result.handle()->IsArgumentsMarker()) {
5076 result = StoreArgumentsObject(false); 5077 result = StoreArgumentsObject(false);
5077 } 5078 }
5078 frame()->Push(&result); 5079 frame()->Push(&result);
5079 return; 5080 return;
5080 } 5081 }
5081 ASSERT(result.is_register()); 5082 ASSERT(result.is_register());
5082 // The loaded value is in a register. If it is the sentinel that 5083 // The loaded value is in a register. If it is the sentinel that
5083 // indicates that we haven't loaded the arguments object yet, we 5084 // indicates that we haven't loaded the arguments object yet, we
5084 // need to do it now. 5085 // need to do it now.
5085 JumpTarget exit; 5086 JumpTarget exit;
5086 __ cmp(Operand(result.reg()), Immediate(Factory::the_hole_value())); 5087 __ cmp(Operand(result.reg()), Immediate(Factory::arguments_marker()));
5087 frame()->Push(&result); 5088 frame()->Push(&result);
5088 exit.Branch(not_equal); 5089 exit.Branch(not_equal);
5089 5090
5090 result = StoreArgumentsObject(false); 5091 result = StoreArgumentsObject(false);
5091 frame()->SetElementAt(0, &result); 5092 frame()->SetElementAt(0, &result);
5092 result.Unuse(); 5093 result.Unuse();
5093 exit.Bind(); 5094 exit.Bind();
5094 return; 5095 return;
5095 } 5096 }
5096 5097
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
5589 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; 5590 if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
5590 // else fall through. 5591 // else fall through.
5591 case ObjectLiteral::Property::COMPUTED: { 5592 case ObjectLiteral::Property::COMPUTED: {
5592 Handle<Object> key(property->key()->handle()); 5593 Handle<Object> key(property->key()->handle());
5593 if (key->IsSymbol()) { 5594 if (key->IsSymbol()) {
5594 // Duplicate the object as the IC receiver. 5595 // Duplicate the object as the IC receiver.
5595 frame_->Dup(); 5596 frame_->Dup();
5596 Load(property->value()); 5597 Load(property->value());
5597 if (property->emit_store()) { 5598 if (property->emit_store()) {
5598 Result ignored = 5599 Result ignored =
5599 frame_->CallStoreIC(Handle<String>::cast(key), false); 5600 frame_->CallStoreIC(Handle<String>::cast(key), false,
5601 strict_mode_flag());
5600 // A test eax instruction following the store IC call would 5602 // A test eax instruction following the store IC call would
5601 // indicate the presence of an inlined version of the 5603 // indicate the presence of an inlined version of the
5602 // store. Add a nop to indicate that there is no such 5604 // store. Add a nop to indicate that there is no such
5603 // inlined version. 5605 // inlined version.
5604 __ nop(); 5606 __ nop();
5605 } else { 5607 } else {
5606 frame_->Drop(2); 5608 frame_->Drop(2);
5607 } 5609 }
5608 break; 5610 break;
5609 } 5611 }
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
6108 NOT_INSIDE_TYPEOF, 6110 NOT_INSIDE_TYPEOF,
6109 &slow); 6111 &slow);
6110 frame_->Push(&fun); 6112 frame_->Push(&fun);
6111 if (arg_count > 0) { 6113 if (arg_count > 0) {
6112 frame_->PushElementAt(arg_count); 6114 frame_->PushElementAt(arg_count);
6113 } else { 6115 } else {
6114 frame_->Push(Factory::undefined_value()); 6116 frame_->Push(Factory::undefined_value());
6115 } 6117 }
6116 frame_->PushParameterAt(-1); 6118 frame_->PushParameterAt(-1);
6117 6119
6120 // Push the strict mode flag.
6121 frame_->Push(Smi::FromInt(strict_mode_flag()));
6122
6118 // Resolve the call. 6123 // Resolve the call.
6119 result = 6124 result =
6120 frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 3); 6125 frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 4);
6121 6126
6122 done.Jump(&result); 6127 done.Jump(&result);
6123 slow.Bind(); 6128 slow.Bind();
6124 } 6129 }
6125 6130
6126 // Prepare the stack for the call to ResolvePossiblyDirectEval by 6131 // Prepare the stack for the call to ResolvePossiblyDirectEval by
6127 // pushing the loaded function, the first argument to the eval 6132 // pushing the loaded function, the first argument to the eval
6128 // call and the receiver. 6133 // call and the receiver.
6129 frame_->PushElementAt(arg_count + 1); 6134 frame_->PushElementAt(arg_count + 1);
6130 if (arg_count > 0) { 6135 if (arg_count > 0) {
6131 frame_->PushElementAt(arg_count); 6136 frame_->PushElementAt(arg_count);
6132 } else { 6137 } else {
6133 frame_->Push(Factory::undefined_value()); 6138 frame_->Push(Factory::undefined_value());
6134 } 6139 }
6135 frame_->PushParameterAt(-1); 6140 frame_->PushParameterAt(-1);
6136 6141
6142 // Push the strict mode flag.
6143 frame_->Push(Smi::FromInt(strict_mode_flag()));
6144
6137 // Resolve the call. 6145 // Resolve the call.
6138 result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); 6146 result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
6139 6147
6140 // If we generated fast-case code bind the jump-target where fast 6148 // If we generated fast-case code bind the jump-target where fast
6141 // and slow case merge. 6149 // and slow case merge.
6142 if (done.is_linked()) done.Bind(&result); 6150 if (done.is_linked()) done.Bind(&result);
6143 6151
6144 // The runtime call returns a pair of values in eax (function) and 6152 // The runtime call returns a pair of values in eax (function) and
6145 // edx (receiver). Touch up the stack with the right values. 6153 // edx (receiver). Touch up the stack with the right values.
6146 Result receiver = allocator_->Allocate(edx); 6154 Result receiver = allocator_->Allocate(edx);
6147 frame_->SetElementAt(arg_count + 1, &result); 6155 frame_->SetElementAt(arg_count + 1, &result);
6148 frame_->SetElementAt(arg_count, &receiver); 6156 frame_->SetElementAt(arg_count, &receiver);
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after
6655 ASSERT(temp.is_valid()); 6663 ASSERT(temp.is_valid());
6656 // Check if the object is a JS array or not. 6664 // Check if the object is a JS array or not.
6657 __ CmpObjectType(value.reg(), JS_ARRAY_TYPE, temp.reg()); 6665 __ CmpObjectType(value.reg(), JS_ARRAY_TYPE, temp.reg());
6658 value.Unuse(); 6666 value.Unuse();
6659 temp.Unuse(); 6667 temp.Unuse();
6660 destination()->Split(equal); 6668 destination()->Split(equal);
6661 } 6669 }
6662 6670
6663 6671
6664 void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) { 6672 void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) {
6673 Label bailout, done, one_char_separator, long_separator,
6674 non_trivial_array, not_size_one_array, loop, loop_condition,
6675 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
6676
6665 ASSERT(args->length() == 2); 6677 ASSERT(args->length() == 2);
6678 // We will leave the separator on the stack until the end of the function.
6666 Load(args->at(1)); 6679 Load(args->at(1));
6680 // Load this to eax (= array)
6667 Load(args->at(0)); 6681 Load(args->at(0));
6668 Result array_result = frame_->Pop(); 6682 Result array_result = frame_->Pop();
6669 array_result.ToRegister(eax); 6683 array_result.ToRegister(eax);
6670 frame_->SpillAll(); 6684 frame_->SpillAll();
6671 6685
6672 Label bailout;
6673 Label done;
6674 // All aliases of the same register have disjoint lifetimes. 6686 // All aliases of the same register have disjoint lifetimes.
6675 Register array = eax; 6687 Register array = eax;
6676 Register result_pos = no_reg; 6688 Register elements = no_reg; // Will be eax.
6677 6689
6678 Register index = edi; 6690 Register index = edx;
6679 6691
6680 Register current_string_length = ecx; // Will be ecx when live. 6692 Register string_length = ecx;
6681 6693
6682 Register current_string = edx; 6694 Register string = esi;
6683 6695
6684 Register scratch = ebx; 6696 Register scratch = ebx;
6685 6697
6686 Register scratch_2 = esi; 6698 Register array_length = edi;
6687 Register new_padding_chars = scratch_2; 6699 Register result_pos = no_reg; // Will be edi.
6688 6700
6689 Operand separator = Operand(esp, 4 * kPointerSize); // Already pushed. 6701 // Separator operand is already pushed.
6690 Operand elements = Operand(esp, 3 * kPointerSize); 6702 Operand separator_operand = Operand(esp, 2 * kPointerSize);
6691 Operand result = Operand(esp, 2 * kPointerSize); 6703 Operand result_operand = Operand(esp, 1 * kPointerSize);
6692 Operand padding_chars = Operand(esp, 1 * kPointerSize); 6704 Operand array_length_operand = Operand(esp, 0);
6693 Operand array_length = Operand(esp, 0); 6705 __ sub(Operand(esp), Immediate(2 * kPointerSize));
6694 __ sub(Operand(esp), Immediate(4 * kPointerSize)); 6706 __ cld();
6695 6707 // Check that the array is a JSArray
6696 // Check that eax is a JSArray
6697 __ test(array, Immediate(kSmiTagMask)); 6708 __ test(array, Immediate(kSmiTagMask));
6698 __ j(zero, &bailout); 6709 __ j(zero, &bailout);
6699 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 6710 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
6700 __ j(not_equal, &bailout); 6711 __ j(not_equal, &bailout);
6701 6712
6702 // Check that the array has fast elements. 6713 // Check that the array has fast elements.
6703 __ test_b(FieldOperand(scratch, Map::kBitField2Offset), 6714 __ test_b(FieldOperand(scratch, Map::kBitField2Offset),
6704 1 << Map::kHasFastElements); 6715 1 << Map::kHasFastElements);
6705 __ j(zero, &bailout); 6716 __ j(zero, &bailout);
6706 6717
6707 // If the array is empty, return the empty string. 6718 // If the array has length zero, return the empty string.
6708 __ mov(scratch, FieldOperand(array, JSArray::kLengthOffset)); 6719 __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
6709 __ sar(scratch, 1); 6720 __ sar(array_length, 1);
6710 Label non_trivial; 6721 __ j(not_zero, &non_trivial_array);
6711 __ j(not_zero, &non_trivial); 6722 __ mov(result_operand, Factory::empty_string());
6712 __ mov(result, Factory::empty_string()); 6723 __ jmp(&done);
6713 __ jmp(&done); 6724
6714 6725 // Save the array length.
6715 __ bind(&non_trivial); 6726 __ bind(&non_trivial_array);
6716 __ mov(array_length, scratch); 6727 __ mov(array_length_operand, array_length);
6717 6728
6718 __ mov(scratch, FieldOperand(array, JSArray::kElementsOffset)); 6729 // Save the FixedArray containing array's elements.
6719 __ mov(elements, scratch);
6720
6721 // End of array's live range. 6730 // End of array's live range.
6722 result_pos = array; 6731 elements = array;
6732 __ mov(elements, FieldOperand(array, JSArray::kElementsOffset));
6723 array = no_reg; 6733 array = no_reg;
6724 6734
6725 6735
6726 // Check that the separator is a flat ascii string. 6736 // Check that all array elements are sequential ASCII strings, and
6727 __ mov(current_string, separator); 6737 // accumulate the sum of their lengths, as a smi-encoded value.
6728 __ test(current_string, Immediate(kSmiTagMask)); 6738 __ Set(index, Immediate(0));
6739 __ Set(string_length, Immediate(0));
6740 // Loop condition: while (index < length).
6741 // Live loop registers: index, array_length, string,
6742 // scratch, string_length, elements.
6743 __ jmp(&loop_condition);
6744 __ bind(&loop);
6745 __ cmp(index, Operand(array_length));
6746 __ j(greater_equal, &done);
6747
6748 __ mov(string, FieldOperand(elements, index,
6749 times_pointer_size,
6750 FixedArray::kHeaderSize));
6751 __ test(string, Immediate(kSmiTagMask));
6729 __ j(zero, &bailout); 6752 __ j(zero, &bailout);
6730 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); 6753 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
6731 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 6754 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
6732 __ and_(scratch, Immediate( 6755 __ and_(scratch, Immediate(
6733 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 6756 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
6734 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 6757 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
6735 __ j(not_equal, &bailout); 6758 __ j(not_equal, &bailout);
6736 // If the separator is the empty string, replace it with NULL. 6759 __ add(string_length,
6737 // The test for NULL is quicker than the empty string test, in a loop. 6760 FieldOperand(string, SeqAsciiString::kLengthOffset));
6738 __ cmp(FieldOperand(current_string, SeqAsciiString::kLengthOffset), 6761 __ j(overflow, &bailout);
6739 Immediate(0)); 6762 __ add(Operand(index), Immediate(1));
6740 Label separator_checked; 6763 __ bind(&loop_condition);
6741 __ j(not_zero, &separator_checked); 6764 __ cmp(index, Operand(array_length));
6742 __ mov(separator, Immediate(0)); 6765 __ j(less, &loop);
6743 __ bind(&separator_checked); 6766
6744 6767 // If array_length is 1, return elements[0], a string.
6745 // Check that elements[0] is a flat ascii string, and copy it in new space. 6768 __ cmp(array_length, 1);
6746 __ mov(scratch, elements); 6769 __ j(not_equal, &not_size_one_array);
6747 __ mov(current_string, FieldOperand(scratch, FixedArray::kHeaderSize)); 6770 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize));
6748 __ test(current_string, Immediate(kSmiTagMask)); 6771 __ mov(result_operand, scratch);
6772 __ jmp(&done);
6773
6774 __ bind(&not_size_one_array);
6775
6776 // End of array_length live range.
6777 result_pos = array_length;
6778 array_length = no_reg;
6779
6780 // Live registers:
6781 // string_length: Sum of string lengths, as a smi.
6782 // elements: FixedArray of strings.
6783
6784 // Check that the separator is a flat ASCII string.
6785 __ mov(string, separator_operand);
6786 __ test(string, Immediate(kSmiTagMask));
6749 __ j(zero, &bailout); 6787 __ j(zero, &bailout);
6750 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); 6788 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
6751 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 6789 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
6752 __ and_(scratch, Immediate( 6790 __ and_(scratch, Immediate(
6753 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 6791 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
6754 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 6792 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
6755 __ j(not_equal, &bailout); 6793 __ j(not_equal, &bailout);
6756 6794
6757 // Allocate space to copy it. Round up the size to the alignment granularity. 6795 // Add (separator length times array_length) - separator length
6758 __ mov(current_string_length, 6796 // to string_length.
6759 FieldOperand(current_string, String::kLengthOffset)); 6797 __ mov(scratch, separator_operand);
6760 __ shr(current_string_length, 1); 6798 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset));
6761 6799 __ sub(string_length, Operand(scratch)); // May be negative, temporarily.
6800 __ imul(scratch, array_length_operand);
6801 __ j(overflow, &bailout);
6802 __ add(string_length, Operand(scratch));
6803 __ j(overflow, &bailout);
6804
6805 __ shr(string_length, 1);
6762 // Live registers and stack values: 6806 // Live registers and stack values:
6763 // current_string_length: length of elements[0]. 6807 // string_length
6764 6808 // elements
6765 // New string result in new space = elements[0] 6809 __ AllocateAsciiString(result_pos, string_length, scratch,
6766 __ AllocateAsciiString(result_pos, current_string_length, scratch_2, 6810 index, string, &bailout);
6767 index, no_reg, &bailout); 6811 __ mov(result_operand, result_pos);
6768 __ mov(result, result_pos); 6812 __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize));
6769 6813
6770 // Adjust current_string_length to include padding bytes at end of string. 6814
6771 // Keep track of the number of padding bytes. 6815 __ mov(string, separator_operand);
6772 __ mov(new_padding_chars, current_string_length); 6816 __ cmp(FieldOperand(string, SeqAsciiString::kLengthOffset),
6773 __ add(Operand(current_string_length), Immediate(kObjectAlignmentMask)); 6817 Immediate(Smi::FromInt(1)));
6774 __ and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask)); 6818 __ j(equal, &one_char_separator);
6775 __ sub(new_padding_chars, Operand(current_string_length)); 6819 __ j(greater, &long_separator);
6776 __ neg(new_padding_chars); 6820
6777 __ mov(padding_chars, new_padding_chars); 6821
6778 6822 // Empty separator case
6779 Label copy_loop_1_done; 6823 __ mov(index, Immediate(0));
6780 Label copy_loop_1; 6824 __ jmp(&loop_1_condition);
6781 __ test(current_string_length, Operand(current_string_length)); 6825 // Loop condition: while (index < length).
6782 __ j(zero, &copy_loop_1_done); 6826 __ bind(&loop_1);
6783 __ bind(&copy_loop_1); 6827 // Each iteration of the loop concatenates one string to the result.
6784 __ sub(Operand(current_string_length), Immediate(kPointerSize)); 6828 // Live values in registers:
6785 __ mov(scratch, FieldOperand(current_string, current_string_length, 6829 // index: which element of the elements array we are adding to the result.
6786 times_1, SeqAsciiString::kHeaderSize)); 6830 // result_pos: the position to which we are currently copying characters.
6787 __ mov(FieldOperand(result_pos, current_string_length, 6831 // elements: the FixedArray of strings we are joining.
6788 times_1, SeqAsciiString::kHeaderSize), 6832
6789 scratch); 6833 // Get string = array[index].
6790 __ j(not_zero, &copy_loop_1); 6834 __ mov(string, FieldOperand(elements, index,
6791 __ bind(&copy_loop_1_done); 6835 times_pointer_size,
6792 6836 FixedArray::kHeaderSize));
6793 __ mov(index, Immediate(1)); 6837 __ mov(string_length,
6794 // Loop condition: while (index < length). 6838 FieldOperand(string, String::kLengthOffset));
6795 Label loop; 6839 __ shr(string_length, 1);
6796 __ bind(&loop); 6840 __ lea(string,
6797 __ cmp(index, array_length); 6841 FieldOperand(string, SeqAsciiString::kHeaderSize));
6798 __ j(greater_equal, &done); 6842 __ CopyBytes(string, result_pos, string_length, scratch);
6799 6843 __ add(Operand(index), Immediate(1));
6800 // If the separator is the empty string, signalled by NULL, skip it. 6844 __ bind(&loop_1_condition);
6801 Label separator_done; 6845 __ cmp(index, array_length_operand);
6802 __ mov(current_string, separator); 6846 __ j(less, &loop_1); // End while (index < length).
6803 __ test(current_string, Operand(current_string)); 6847 __ jmp(&done);
6804 __ j(zero, &separator_done); 6848
6805 6849
6806 // Append separator to result. It is known to be a flat ascii string. 6850
6807 __ AppendStringToTopOfNewSpace(current_string, current_string_length, 6851 // One-character separator case
6808 result_pos, scratch, scratch_2, result, 6852 __ bind(&one_char_separator);
6809 padding_chars, &bailout); 6853 // Replace separator with its ascii character value.
6810 __ bind(&separator_done); 6854 __ mov_b(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize));
6811 6855 __ mov_b(separator_operand, scratch);
6812 // Add next element of array to the end of the result. 6856
6813 // Get current_string = array[index]. 6857 __ Set(index, Immediate(0));
6814 __ mov(scratch, elements); 6858 // Jump into the loop after the code that copies the separator, so the first
6815 __ mov(current_string, FieldOperand(scratch, index, 6859 // element is not preceded by a separator
6816 times_pointer_size, 6860 __ jmp(&loop_2_entry);
6817 FixedArray::kHeaderSize)); 6861 // Loop condition: while (index < length).
6818 // If current != flat ascii string drop result, return undefined. 6862 __ bind(&loop_2);
6819 __ test(current_string, Immediate(kSmiTagMask)); 6863 // Each iteration of the loop concatenates one string to the result.
6820 __ j(zero, &bailout); 6864 // Live values in registers:
6821 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); 6865 // index: which element of the elements array we are adding to the result.
6822 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 6866 // result_pos: the position to which we are currently copying characters.
6823 __ and_(scratch, Immediate( 6867
6824 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 6868 // Copy the separator character to the result.
6825 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 6869 __ mov_b(scratch, separator_operand);
6826 __ j(not_equal, &bailout); 6870 __ mov_b(Operand(result_pos, 0), scratch);
6827 6871 __ inc(result_pos);
6828 // Append current to the result. 6872
6829 __ AppendStringToTopOfNewSpace(current_string, current_string_length, 6873 __ bind(&loop_2_entry);
6830 result_pos, scratch, scratch_2, result, 6874 // Get string = array[index].
6831 padding_chars, &bailout); 6875 __ mov(string, FieldOperand(elements, index,
6832 __ add(Operand(index), Immediate(1)); 6876 times_pointer_size,
6833 __ jmp(&loop); // End while (index < length). 6877 FixedArray::kHeaderSize));
6878 __ mov(string_length,
6879 FieldOperand(string, String::kLengthOffset));
6880 __ shr(string_length, 1);
6881 __ lea(string,
6882 FieldOperand(string, SeqAsciiString::kHeaderSize));
6883 __ CopyBytes(string, result_pos, string_length, scratch);
6884 __ add(Operand(index), Immediate(1));
6885
6886 __ cmp(index, array_length_operand);
6887 __ j(less, &loop_2); // End while (index < length).
6888 __ jmp(&done);
6889
6890
6891 // Long separator case (separator is more than one character).
6892 __ bind(&long_separator);
6893
6894 __ Set(index, Immediate(0));
6895 // Jump into the loop after the code that copies the separator, so the first
6896 // element is not preceded by a separator
6897 __ jmp(&loop_3_entry);
6898 // Loop condition: while (index < length).
6899 __ bind(&loop_3);
6900 // Each iteration of the loop concatenates one string to the result.
6901 // Live values in registers:
6902 // index: which element of the elements array we are adding to the result.
6903 // result_pos: the position to which we are currently copying characters.
6904
6905 // Copy the separator to the result.
6906 __ mov(string, separator_operand);
6907 __ mov(string_length,
6908 FieldOperand(string, String::kLengthOffset));
6909 __ shr(string_length, 1);
6910 __ lea(string,
6911 FieldOperand(string, SeqAsciiString::kHeaderSize));
6912 __ CopyBytes(string, result_pos, string_length, scratch);
6913
6914 __ bind(&loop_3_entry);
6915 // Get string = array[index].
6916 __ mov(string, FieldOperand(elements, index,
6917 times_pointer_size,
6918 FixedArray::kHeaderSize));
6919 __ mov(string_length,
6920 FieldOperand(string, String::kLengthOffset));
6921 __ shr(string_length, 1);
6922 __ lea(string,
6923 FieldOperand(string, SeqAsciiString::kHeaderSize));
6924 __ CopyBytes(string, result_pos, string_length, scratch);
6925 __ add(Operand(index), Immediate(1));
6926
6927 __ cmp(index, array_length_operand);
6928 __ j(less, &loop_3); // End while (index < length).
6929 __ jmp(&done);
6930
6834 6931
6835 __ bind(&bailout); 6932 __ bind(&bailout);
6836 __ mov(result, Factory::undefined_value()); 6933 __ mov(result_operand, Factory::undefined_value());
6837 __ bind(&done); 6934 __ bind(&done);
6838 __ mov(eax, result); 6935 __ mov(eax, result_operand);
6839 // Drop temp values from the stack, and restore context register. 6936 // Drop temp values from the stack, and restore context register.
6840 __ add(Operand(esp), Immediate(4 * kPointerSize)); 6937 __ add(Operand(esp), Immediate(2 * kPointerSize));
6841 6938
6842 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 6939 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
6843 frame_->Drop(1); 6940 frame_->Drop(1);
6844 frame_->Push(&array_result); 6941 frame_->Push(&array_result);
6845 } 6942 }
6846 6943
6847 6944
6848 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { 6945 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) {
6849 ASSERT(args->length() == 1); 6946 ASSERT(args->length() == 1);
6850 Load(args->at(0)); 6947 Load(args->at(0));
(...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after
7870 // Test for -0.5. 7967 // Test for -0.5.
7871 // Load xmm2 with -0.5. 7968 // Load xmm2 with -0.5.
7872 __ mov(answer.reg(), Immediate(0xBF000000)); 7969 __ mov(answer.reg(), Immediate(0xBF000000));
7873 __ movd(xmm2, Operand(answer.reg())); 7970 __ movd(xmm2, Operand(answer.reg()));
7874 __ cvtss2sd(xmm2, xmm2); 7971 __ cvtss2sd(xmm2, xmm2);
7875 // xmm2 now has -0.5. 7972 // xmm2 now has -0.5.
7876 __ ucomisd(xmm2, xmm1); 7973 __ ucomisd(xmm2, xmm1);
7877 __ j(not_equal, &not_minus_half); 7974 __ j(not_equal, &not_minus_half);
7878 7975
7879 // Calculates reciprocal of square root. 7976 // Calculates reciprocal of square root.
7880 // Note that 1/sqrt(x) = sqrt(1/x)) 7977 // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
7881 __ divsd(xmm3, xmm0); 7978 __ xorpd(xmm1, xmm1);
7979 __ addsd(xmm1, xmm0);
7980 __ sqrtsd(xmm1, xmm1);
7981 __ divsd(xmm3, xmm1);
7882 __ movsd(xmm1, xmm3); 7982 __ movsd(xmm1, xmm3);
7883 __ sqrtsd(xmm1, xmm1);
7884 __ jmp(&allocate_return); 7983 __ jmp(&allocate_return);
7885 7984
7886 // Test for 0.5. 7985 // Test for 0.5.
7887 __ bind(&not_minus_half); 7986 __ bind(&not_minus_half);
7888 // Load xmm2 with 0.5. 7987 // Load xmm2 with 0.5.
7889 // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3. 7988 // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3.
7890 __ addsd(xmm2, xmm3); 7989 __ addsd(xmm2, xmm3);
7891 // xmm2 now has 0.5. 7990 // xmm2 now has 0.5.
7892 __ ucomisd(xmm2, xmm1); 7991 __ ucomisd(xmm2, xmm1);
7893 call_runtime.Branch(not_equal); 7992 call_runtime.Branch(not_equal);
7894 // Calculates square root. 7993 // Calculates square root.
7895 __ movsd(xmm1, xmm0); 7994 // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
7995 __ xorpd(xmm1, xmm1);
7996 __ addsd(xmm1, xmm0);
7896 __ sqrtsd(xmm1, xmm1); 7997 __ sqrtsd(xmm1, xmm1);
7897 7998
7898 JumpTarget done; 7999 JumpTarget done;
7899 Label failure, success; 8000 Label failure, success;
7900 __ bind(&allocate_return); 8001 __ bind(&allocate_return);
7901 // Make a copy of the frame to enable us to handle allocation 8002 // Make a copy of the frame to enable us to handle allocation
7902 // failure after the JumpTarget jump. 8003 // failure after the JumpTarget jump.
7903 VirtualFrame* clone = new VirtualFrame(frame()); 8004 VirtualFrame* clone = new VirtualFrame(frame());
7904 __ AllocateHeapNumber(answer.reg(), exponent.reg(), 8005 __ AllocateHeapNumber(answer.reg(), exponent.reg(),
7905 base.reg(), &failure); 8006 base.reg(), &failure);
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
8132 destination()->Invert(); 8233 destination()->Invert();
8133 LoadCondition(node->expression(), destination(), true); 8234 LoadCondition(node->expression(), destination(), true);
8134 // Swap the labels back. 8235 // Swap the labels back.
8135 destination()->Invert(); 8236 destination()->Invert();
8136 8237
8137 } else if (op == Token::DELETE) { 8238 } else if (op == Token::DELETE) {
8138 Property* property = node->expression()->AsProperty(); 8239 Property* property = node->expression()->AsProperty();
8139 if (property != NULL) { 8240 if (property != NULL) {
8140 Load(property->obj()); 8241 Load(property->obj());
8141 Load(property->key()); 8242 Load(property->key());
8142 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); 8243 frame_->Push(Smi::FromInt(strict_mode_flag()));
8244 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3);
8143 frame_->Push(&answer); 8245 frame_->Push(&answer);
8144 return; 8246 return;
8145 } 8247 }
8146 8248
8147 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); 8249 Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
8148 if (variable != NULL) { 8250 if (variable != NULL) {
8251 // Delete of an unqualified identifier is disallowed in strict mode
8252 // so this code can only be reached in non-strict mode.
8253 ASSERT(strict_mode_flag() == kNonStrictMode);
8149 Slot* slot = variable->AsSlot(); 8254 Slot* slot = variable->AsSlot();
8150 if (variable->is_global()) { 8255 if (variable->is_global()) {
8151 LoadGlobal(); 8256 LoadGlobal();
8152 frame_->Push(variable->name()); 8257 frame_->Push(variable->name());
8258 frame_->Push(Smi::FromInt(kNonStrictMode));
8153 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, 8259 Result answer = frame_->InvokeBuiltin(Builtins::DELETE,
8154 CALL_FUNCTION, 2); 8260 CALL_FUNCTION, 3);
8155 frame_->Push(&answer); 8261 frame_->Push(&answer);
8156 return; 8262 return;
8157 8263
8158 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 8264 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
8159 // Call the runtime to look up the context holding the named 8265 // Call the runtime to delete from the context holding the named
8160 // variable. Sync the virtual frame eagerly so we can push the 8266 // variable. Sync the virtual frame eagerly so we can push the
8161 // arguments directly into place. 8267 // arguments directly into place.
8162 frame_->SyncRange(0, frame_->element_count() - 1); 8268 frame_->SyncRange(0, frame_->element_count() - 1);
8163 frame_->EmitPush(esi); 8269 frame_->EmitPush(esi);
8164 frame_->EmitPush(Immediate(variable->name())); 8270 frame_->EmitPush(Immediate(variable->name()));
8165 Result context = frame_->CallRuntime(Runtime::kLookupContext, 2); 8271 Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2);
8166 ASSERT(context.is_register());
8167 frame_->EmitPush(context.reg());
8168 context.Unuse();
8169 frame_->EmitPush(Immediate(variable->name()));
8170 Result answer = frame_->InvokeBuiltin(Builtins::DELETE,
8171 CALL_FUNCTION, 2);
8172 frame_->Push(&answer); 8272 frame_->Push(&answer);
8173 return; 8273 return;
8174 } 8274 }
8175 8275
8176 // Default: Result of deleting non-global, not dynamically 8276 // Default: Result of deleting non-global, not dynamically
8177 // introduced variables is false. 8277 // introduced variables is false.
8178 frame_->Push(Factory::false_value()); 8278 frame_->Push(Factory::false_value());
8179 8279
8180 } else { 8280 } else {
8181 // Default: Result of deleting expressions is true. 8281 // Default: Result of deleting expressions is true.
(...skipping 1403 matching lines...) Expand 10 before | Expand all | Expand 10 after
9585 } 9685 }
9586 9686
9587 9687
9588 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { 9688 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
9589 #ifdef DEBUG 9689 #ifdef DEBUG
9590 int expected_height = frame()->height() - (is_contextual ? 1 : 2); 9690 int expected_height = frame()->height() - (is_contextual ? 1 : 2);
9591 #endif 9691 #endif
9592 9692
9593 Result result; 9693 Result result;
9594 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { 9694 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) {
9595 result = frame()->CallStoreIC(name, is_contextual); 9695 result = frame()->CallStoreIC(name, is_contextual, strict_mode_flag());
9596 // A test eax instruction following the call signals that the inobject 9696 // A test eax instruction following the call signals that the inobject
9597 // property case was inlined. Ensure that there is not a test eax 9697 // property case was inlined. Ensure that there is not a test eax
9598 // instruction here. 9698 // instruction here.
9599 __ nop(); 9699 __ nop();
9600 } else { 9700 } else {
9601 // Inline the in-object property case. 9701 // Inline the in-object property case.
9602 JumpTarget slow, done; 9702 JumpTarget slow, done;
9603 Label patch_site; 9703 Label patch_site;
9604 9704
9605 // Get the value and receiver from the stack. 9705 // Get the value and receiver from the stack.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
9672 } 9772 }
9673 __ bind(&skip_write_barrier); 9773 __ bind(&skip_write_barrier);
9674 value.Unuse(); 9774 value.Unuse();
9675 scratch.Unuse(); 9775 scratch.Unuse();
9676 receiver.Unuse(); 9776 receiver.Unuse();
9677 done.Jump(&result); 9777 done.Jump(&result);
9678 9778
9679 slow.Bind(&value, &receiver); 9779 slow.Bind(&value, &receiver);
9680 frame()->Push(&receiver); 9780 frame()->Push(&receiver);
9681 frame()->Push(&value); 9781 frame()->Push(&value);
9682 result = frame()->CallStoreIC(name, is_contextual); 9782 result = frame()->CallStoreIC(name, is_contextual, strict_mode_flag());
9683 // Encode the offset to the map check instruction and the offset 9783 // Encode the offset to the map check instruction and the offset
9684 // to the write barrier store address computation in a test eax 9784 // to the write barrier store address computation in a test eax
9685 // instruction. 9785 // instruction.
9686 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site); 9786 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site);
9687 __ test(eax, 9787 __ test(eax,
9688 Immediate((delta_to_record_write << 16) | delta_to_patch_site)); 9788 Immediate((delta_to_record_write << 16) | delta_to_patch_site));
9689 done.Bind(&result); 9789 done.Bind(&result);
9690 } 9790 }
9691 9791
9692 ASSERT_EQ(expected_height, frame()->height()); 9792 ASSERT_EQ(expected_height, frame()->height());
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
10249 memcpy(base, desc.buffer, desc.instr_size); 10349 memcpy(base, desc.buffer, desc.instr_size);
10250 CPU::FlushICache(base, desc.instr_size); 10350 CPU::FlushICache(base, desc.instr_size);
10251 return FUNCTION_CAST<MemCopyFunction>(reinterpret_cast<Address>(base)); 10351 return FUNCTION_CAST<MemCopyFunction>(reinterpret_cast<Address>(base));
10252 } 10352 }
10253 10353
10254 #undef __ 10354 #undef __
10255 10355
10256 } } // namespace v8::internal 10356 } } // namespace v8::internal
10257 10357
10258 #endif // V8_TARGET_ARCH_IA32 10358 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698