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

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

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: 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/arm/codegen-arm.h ('k') | src/arm/constants-arm.h » ('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 563 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 Register reg = frame_->GetTOSRegister(); 574 Register reg = frame_->GetTOSRegister();
575 __ ldr(reg, ContextOperand(cp, Context::GLOBAL_INDEX)); 575 __ ldr(reg, ContextOperand(cp, Context::GLOBAL_INDEX));
576 __ ldr(reg, 576 __ ldr(reg,
577 FieldMemOperand(reg, GlobalObject::kGlobalReceiverOffset)); 577 FieldMemOperand(reg, GlobalObject::kGlobalReceiverOffset));
578 frame_->EmitPush(reg); 578 frame_->EmitPush(reg);
579 } 579 }
580 580
581 581
582 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { 582 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
583 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; 583 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
584 ASSERT(scope()->arguments_shadow() != NULL); 584
585 // In strict mode there is no need for shadow arguments.
586 ASSERT(scope()->arguments_shadow() != NULL || scope()->is_strict_mode());
585 // We don't want to do lazy arguments allocation for functions that 587 // We don't want to do lazy arguments allocation for functions that
586 // have heap-allocated contexts, because it interfers with the 588 // have heap-allocated contexts, because it interfers with the
587 // uninitialized const tracking in the context objects. 589 // uninitialized const tracking in the context objects.
588 return (scope()->num_heap_slots() > 0) 590 return (scope()->num_heap_slots() > 0 || scope()->is_strict_mode())
589 ? EAGER_ARGUMENTS_ALLOCATION 591 ? EAGER_ARGUMENTS_ALLOCATION
590 : LAZY_ARGUMENTS_ALLOCATION; 592 : LAZY_ARGUMENTS_ALLOCATION;
591 } 593 }
592 594
593 595
594 void CodeGenerator::StoreArgumentsObject(bool initial) { 596 void CodeGenerator::StoreArgumentsObject(bool initial) {
595 ArgumentsAllocationMode mode = ArgumentsMode(); 597 ArgumentsAllocationMode mode = ArgumentsMode();
596 ASSERT(mode != NO_ARGUMENTS_ALLOCATION); 598 ASSERT(mode != NO_ARGUMENTS_ALLOCATION);
597 599
598 Comment cmnt(masm_, "[ store arguments object"); 600 Comment cmnt(masm_, "[ store arguments object");
(...skipping 13 matching lines...) Expand all
612 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); 614 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
613 frame_->Adjust(3); 615 frame_->Adjust(3);
614 __ Push(r2, r1, r0); 616 __ Push(r2, r1, r0);
615 frame_->CallStub(&stub, 3); 617 frame_->CallStub(&stub, 3);
616 frame_->EmitPush(r0); 618 frame_->EmitPush(r0);
617 } 619 }
618 620
619 Variable* arguments = scope()->arguments(); 621 Variable* arguments = scope()->arguments();
620 Variable* shadow = scope()->arguments_shadow(); 622 Variable* shadow = scope()->arguments_shadow();
621 ASSERT(arguments != NULL && arguments->AsSlot() != NULL); 623 ASSERT(arguments != NULL && arguments->AsSlot() != NULL);
622 ASSERT(shadow != NULL && shadow->AsSlot() != NULL); 624 ASSERT((shadow != NULL && shadow->AsSlot() != NULL) ||
625 scope()->is_strict_mode());
626
623 JumpTarget done; 627 JumpTarget done;
624 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { 628 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
625 // We have to skip storing into the arguments slot if it has 629 // We have to skip storing into the arguments slot if it has
626 // already been written to. This can happen if the a function 630 // already been written to. This can happen if the a function
627 // has a local variable named 'arguments'. 631 // has a local variable named 'arguments'.
628 LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF); 632 LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF);
629 Register arguments = frame_->PopToRegister(); 633 Register arguments = frame_->PopToRegister();
630 __ LoadRoot(ip, Heap::kArgumentsMarkerRootIndex); 634 __ LoadRoot(ip, Heap::kArgumentsMarkerRootIndex);
631 __ cmp(arguments, ip); 635 __ cmp(arguments, ip);
632 done.Branch(ne); 636 done.Branch(ne);
633 } 637 }
634 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT); 638 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT);
635 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); 639 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
636 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT); 640 if (shadow != NULL) {
641 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
642 }
637 } 643 }
638 644
639 645
640 void CodeGenerator::LoadTypeofExpression(Expression* expr) { 646 void CodeGenerator::LoadTypeofExpression(Expression* expr) {
641 // Special handling of identifiers as subexpressions of typeof. 647 // Special handling of identifiers as subexpressions of typeof.
642 Variable* variable = expr->AsVariableProxy()->AsVariable(); 648 Variable* variable = expr->AsVariableProxy()->AsVariable();
643 if (variable != NULL && !variable->is_this() && variable->is_global()) { 649 if (variable != NULL && !variable->is_this() && variable->is_global()) {
644 // For a global variable we build the property reference 650 // For a global variable we build the property reference
645 // <global>.<variable> and perform a (regular non-contextual) property 651 // <global>.<variable> and perform a (regular non-contextual) property
646 // load to make sure we do not get reference errors. 652 // load to make sure we do not get reference errors.
(...skipping 1288 matching lines...) Expand 10 before | Expand all | Expand 10 after
1935 } 1941 }
1936 node->break_target()->Unuse(); 1942 node->break_target()->Unuse();
1937 ASSERT(!has_valid_frame() || frame_->height() == original_height); 1943 ASSERT(!has_valid_frame() || frame_->height() == original_height);
1938 } 1944 }
1939 1945
1940 1946
1941 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1947 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1942 frame_->EmitPush(cp); 1948 frame_->EmitPush(cp);
1943 frame_->EmitPush(Operand(pairs)); 1949 frame_->EmitPush(Operand(pairs));
1944 frame_->EmitPush(Operand(Smi::FromInt(is_eval() ? 1 : 0))); 1950 frame_->EmitPush(Operand(Smi::FromInt(is_eval() ? 1 : 0)));
1951 frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
1945 1952
1946 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 1953 frame_->CallRuntime(Runtime::kDeclareGlobals, 4);
1947 // The result is discarded. 1954 // The result is discarded.
1948 } 1955 }
1949 1956
1950 1957
1951 void CodeGenerator::VisitDeclaration(Declaration* node) { 1958 void CodeGenerator::VisitDeclaration(Declaration* node) {
1952 #ifdef DEBUG 1959 #ifdef DEBUG
1953 int original_height = frame_->height(); 1960 int original_height = frame_->height();
1954 #endif 1961 #endif
1955 Comment cmnt(masm_, "[ Declaration"); 1962 Comment cmnt(masm_, "[ Declaration");
1956 Variable* var = node->proxy()->var(); 1963 Variable* var = node->proxy()->var();
(...skipping 1327 matching lines...) Expand 10 before | Expand all | Expand 10 after
3284 // context slot declaration, but we cannot initialize it at the 3291 // context slot declaration, but we cannot initialize it at the
3285 // same time, because the const declaration may be at the end of 3292 // same time, because the const declaration may be at the end of
3286 // the eval code (sigh...) and the const variable may have been 3293 // the eval code (sigh...) and the const variable may have been
3287 // used before (where its value is 'undefined'). Thus, we can only 3294 // used before (where its value is 'undefined'). Thus, we can only
3288 // do the initialization when we actually encounter the expression 3295 // do the initialization when we actually encounter the expression
3289 // and when the expression operands are defined and valid, and 3296 // and when the expression operands are defined and valid, and
3290 // thus we need the split into 2 operations: declaration of the 3297 // thus we need the split into 2 operations: declaration of the
3291 // context slot followed by initialization. 3298 // context slot followed by initialization.
3292 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); 3299 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
3293 } else { 3300 } else {
3294 frame_->CallRuntime(Runtime::kStoreContextSlot, 3); 3301 frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
3302 frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
3295 } 3303 }
3296 // Storing a variable must keep the (new) value on the expression 3304 // Storing a variable must keep the (new) value on the expression
3297 // stack. This is necessary for compiling assignment expressions. 3305 // stack. This is necessary for compiling assignment expressions.
3298 frame_->EmitPush(r0); 3306 frame_->EmitPush(r0);
3299 3307
3300 } else { 3308 } else {
3301 ASSERT(!slot->var()->is_dynamic()); 3309 ASSERT(!slot->var()->is_dynamic());
3302 Register scratch = VirtualFrame::scratch0(); 3310 Register scratch = VirtualFrame::scratch0();
3303 Register scratch2 = VirtualFrame::scratch1(); 3311 Register scratch2 = VirtualFrame::scratch1();
3304 3312
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
3636 frame_->Drop(); 3644 frame_->Drop();
3637 } 3645 }
3638 break; 3646 break;
3639 } 3647 }
3640 // else fall through 3648 // else fall through
3641 case ObjectLiteral::Property::PROTOTYPE: { 3649 case ObjectLiteral::Property::PROTOTYPE: {
3642 frame_->Dup(); 3650 frame_->Dup();
3643 Load(key); 3651 Load(key);
3644 Load(value); 3652 Load(value);
3645 if (property->emit_store()) { 3653 if (property->emit_store()) {
3646 frame_->CallRuntime(Runtime::kSetProperty, 3); 3654 frame_->EmitPush(Operand(Smi::FromInt(NONE))); // PropertyAttributes
3655 frame_->CallRuntime(Runtime::kSetProperty, 4);
3647 } else { 3656 } else {
3648 frame_->Drop(3); 3657 frame_->Drop(3);
3649 } 3658 }
3650 break; 3659 break;
3651 } 3660 }
3652 case ObjectLiteral::Property::SETTER: { 3661 case ObjectLiteral::Property::SETTER: {
3653 frame_->Dup(); 3662 frame_->Dup();
3654 Load(key); 3663 Load(key);
3655 frame_->EmitPush(Operand(Smi::FromInt(1))); 3664 frame_->EmitPush(Operand(Smi::FromInt(1)));
3656 Load(value); 3665 Load(value);
(...skipping 1516 matching lines...) Expand 10 before | Expand all | Expand 10 after
5173 __ ldr(scratch2_, 5182 __ ldr(scratch2_,
5174 FieldMemOperand(scratch2_, GlobalObject::kGlobalContextOffset)); 5183 FieldMemOperand(scratch2_, GlobalObject::kGlobalContextOffset));
5175 __ ldr(scratch2_, 5184 __ ldr(scratch2_,
5176 ContextOperand( 5185 ContextOperand(
5177 scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 5186 scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
5178 __ cmp(scratch1_, scratch2_); 5187 __ cmp(scratch1_, scratch2_);
5179 __ b(ne, &false_result); 5188 __ b(ne, &false_result);
5180 5189
5181 // Set the bit in the map to indicate that it has been checked safe for 5190 // Set the bit in the map to indicate that it has been checked safe for
5182 // default valueOf and set true result. 5191 // default valueOf and set true result.
5183 __ ldr(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset)); 5192 __ ldrb(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset));
5184 __ orr(scratch1_, 5193 __ orr(scratch1_,
5185 scratch1_, 5194 scratch1_,
5186 Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 5195 Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
5187 __ str(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset)); 5196 __ strb(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset));
5188 __ mov(map_result_, Operand(1)); 5197 __ mov(map_result_, Operand(1));
5189 __ jmp(exit_label()); 5198 __ jmp(exit_label());
5190 __ bind(&false_result); 5199 __ bind(&false_result);
5191 // Set false result. 5200 // Set false result.
5192 __ mov(map_result_, Operand(0, RelocInfo::NONE)); 5201 __ mov(map_result_, Operand(0, RelocInfo::NONE));
5193 } 5202 }
5194 5203
5195 private: 5204 private:
5196 Register object_; 5205 Register object_;
5197 Register map_result_; 5206 Register map_result_;
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
5578 frame_->EmitPop(index2); 5587 frame_->EmitPop(index2);
5579 frame_->EmitPop(index1); 5588 frame_->EmitPop(index1);
5580 frame_->EmitPop(object); 5589 frame_->EmitPop(object);
5581 5590
5582 DeferredSwapElements* deferred = 5591 DeferredSwapElements* deferred =
5583 new DeferredSwapElements(object, index1, index2); 5592 new DeferredSwapElements(object, index1, index2);
5584 5593
5585 // Fetch the map and check if array is in fast case. 5594 // Fetch the map and check if array is in fast case.
5586 // Check that object doesn't require security checks and 5595 // Check that object doesn't require security checks and
5587 // has no indexed interceptor. 5596 // has no indexed interceptor.
5588 __ CompareObjectType(object, tmp1, tmp2, FIRST_JS_OBJECT_TYPE); 5597 __ CompareObjectType(object, tmp1, tmp2, JS_ARRAY_TYPE);
5589 deferred->Branch(lt); 5598 deferred->Branch(ne);
5590 __ ldrb(tmp2, FieldMemOperand(tmp1, Map::kBitFieldOffset)); 5599 __ ldrb(tmp2, FieldMemOperand(tmp1, Map::kBitFieldOffset));
5591 __ tst(tmp2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask)); 5600 __ tst(tmp2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask));
5592 deferred->Branch(ne); 5601 deferred->Branch(ne);
5593 5602
5594 // Check the object's elements are in fast case and writable. 5603 // Check the object's elements are in fast case and writable.
5595 __ ldr(tmp1, FieldMemOperand(object, JSObject::kElementsOffset)); 5604 __ ldr(tmp1, FieldMemOperand(object, JSObject::kElementsOffset));
5596 __ ldr(tmp2, FieldMemOperand(tmp1, HeapObject::kMapOffset)); 5605 __ ldr(tmp2, FieldMemOperand(tmp1, HeapObject::kMapOffset));
5597 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 5606 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
5598 __ cmp(tmp2, ip); 5607 __ cmp(tmp2, ip);
5599 deferred->Branch(ne); 5608 deferred->Branch(ne);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
5661 Load(args->at(n_args + 1)); // function 5670 Load(args->at(n_args + 1)); // function
5662 frame_->CallJSFunction(n_args); 5671 frame_->CallJSFunction(n_args);
5663 frame_->EmitPush(r0); 5672 frame_->EmitPush(r0);
5664 } 5673 }
5665 5674
5666 5675
5667 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { 5676 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
5668 ASSERT_EQ(args->length(), 1); 5677 ASSERT_EQ(args->length(), 1);
5669 Load(args->at(0)); 5678 Load(args->at(0));
5670 if (CpuFeatures::IsSupported(VFP3)) { 5679 if (CpuFeatures::IsSupported(VFP3)) {
5671 TranscendentalCacheStub stub(TranscendentalCache::SIN); 5680 TranscendentalCacheStub stub(TranscendentalCache::SIN,
5681 TranscendentalCacheStub::TAGGED);
5672 frame_->SpillAllButCopyTOSToR0(); 5682 frame_->SpillAllButCopyTOSToR0();
5673 frame_->CallStub(&stub, 1); 5683 frame_->CallStub(&stub, 1);
5674 } else { 5684 } else {
5675 frame_->CallRuntime(Runtime::kMath_sin, 1); 5685 frame_->CallRuntime(Runtime::kMath_sin, 1);
5676 } 5686 }
5677 frame_->EmitPush(r0); 5687 frame_->EmitPush(r0);
5678 } 5688 }
5679 5689
5680 5690
5681 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { 5691 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
5682 ASSERT_EQ(args->length(), 1); 5692 ASSERT_EQ(args->length(), 1);
5683 Load(args->at(0)); 5693 Load(args->at(0));
5684 if (CpuFeatures::IsSupported(VFP3)) { 5694 if (CpuFeatures::IsSupported(VFP3)) {
5685 TranscendentalCacheStub stub(TranscendentalCache::COS); 5695 TranscendentalCacheStub stub(TranscendentalCache::COS,
5696 TranscendentalCacheStub::TAGGED);
5686 frame_->SpillAllButCopyTOSToR0(); 5697 frame_->SpillAllButCopyTOSToR0();
5687 frame_->CallStub(&stub, 1); 5698 frame_->CallStub(&stub, 1);
5688 } else { 5699 } else {
5689 frame_->CallRuntime(Runtime::kMath_cos, 1); 5700 frame_->CallRuntime(Runtime::kMath_cos, 1);
5690 } 5701 }
5691 frame_->EmitPush(r0); 5702 frame_->EmitPush(r0);
5692 } 5703 }
5693 5704
5694 5705
5695 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) { 5706 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
5696 ASSERT_EQ(args->length(), 1); 5707 ASSERT_EQ(args->length(), 1);
5697 Load(args->at(0)); 5708 Load(args->at(0));
5698 if (CpuFeatures::IsSupported(VFP3)) { 5709 if (CpuFeatures::IsSupported(VFP3)) {
5699 TranscendentalCacheStub stub(TranscendentalCache::LOG); 5710 TranscendentalCacheStub stub(TranscendentalCache::LOG,
5711 TranscendentalCacheStub::TAGGED);
5700 frame_->SpillAllButCopyTOSToR0(); 5712 frame_->SpillAllButCopyTOSToR0();
5701 frame_->CallStub(&stub, 1); 5713 frame_->CallStub(&stub, 1);
5702 } else { 5714 } else {
5703 frame_->CallRuntime(Runtime::kMath_log, 1); 5715 frame_->CallRuntime(Runtime::kMath_log, 1);
5704 } 5716 }
5705 frame_->EmitPush(r0); 5717 frame_->EmitPush(r0);
5706 } 5718 }
5707 5719
5708 5720
5709 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 5721 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
5855 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); 5867 Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
5856 if (property != NULL) { 5868 if (property != NULL) {
5857 Load(property->obj()); 5869 Load(property->obj());
5858 Load(property->key()); 5870 Load(property->key());
5859 frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag()))); 5871 frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
5860 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 3); 5872 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 3);
5861 frame_->EmitPush(r0); 5873 frame_->EmitPush(r0);
5862 5874
5863 } else if (variable != NULL) { 5875 } else if (variable != NULL) {
5864 // Delete of an unqualified identifier is disallowed in strict mode 5876 // Delete of an unqualified identifier is disallowed in strict mode
5865 // so this code can only be reached in non-strict mode. 5877 // but "delete this" is.
5866 ASSERT(strict_mode_flag() == kNonStrictMode); 5878 ASSERT(strict_mode_flag() == kNonStrictMode || variable->is_this());
5867 Slot* slot = variable->AsSlot(); 5879 Slot* slot = variable->AsSlot();
5868 if (variable->is_global()) { 5880 if (variable->is_global()) {
5869 LoadGlobal(); 5881 LoadGlobal();
5870 frame_->EmitPush(Operand(variable->name())); 5882 frame_->EmitPush(Operand(variable->name()));
5871 frame_->EmitPush(Operand(Smi::FromInt(kNonStrictMode))); 5883 frame_->EmitPush(Operand(Smi::FromInt(kNonStrictMode)));
5872 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 3); 5884 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 3);
5873 frame_->EmitPush(r0); 5885 frame_->EmitPush(r0);
5874 5886
5875 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 5887 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
5876 // Delete from the context holding the named variable. 5888 // Delete from the context holding the named variable.
(...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after
6679 // deferred code. 6691 // deferred code.
6680 __ BlockConstPoolFor(1); 6692 __ BlockConstPoolFor(1);
6681 } 6693 }
6682 } 6694 }
6683 6695
6684 6696
6685 class DeferredReferenceSetKeyedValue: public DeferredCode { 6697 class DeferredReferenceSetKeyedValue: public DeferredCode {
6686 public: 6698 public:
6687 DeferredReferenceSetKeyedValue(Register value, 6699 DeferredReferenceSetKeyedValue(Register value,
6688 Register key, 6700 Register key,
6689 Register receiver) 6701 Register receiver,
6690 : value_(value), key_(key), receiver_(receiver) { 6702 StrictModeFlag strict_mode)
6703 : value_(value),
6704 key_(key),
6705 receiver_(receiver),
6706 strict_mode_(strict_mode) {
6691 set_comment("[ DeferredReferenceSetKeyedValue"); 6707 set_comment("[ DeferredReferenceSetKeyedValue");
6692 } 6708 }
6693 6709
6694 virtual void Generate(); 6710 virtual void Generate();
6695 6711
6696 private: 6712 private:
6697 Register value_; 6713 Register value_;
6698 Register key_; 6714 Register key_;
6699 Register receiver_; 6715 Register receiver_;
6716 StrictModeFlag strict_mode_;
6700 }; 6717 };
6701 6718
6702 6719
6703 void DeferredReferenceSetKeyedValue::Generate() { 6720 void DeferredReferenceSetKeyedValue::Generate() {
6704 Register scratch1 = VirtualFrame::scratch0(); 6721 Register scratch1 = VirtualFrame::scratch0();
6705 Register scratch2 = VirtualFrame::scratch1(); 6722 Register scratch2 = VirtualFrame::scratch1();
6706 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2); 6723 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2);
6707 __ IncrementCounter( 6724 __ IncrementCounter(
6708 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2); 6725 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2);
6709 6726
6710 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic 6727 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic
6711 // calling convention. 6728 // calling convention.
6712 if (value_.is(r1)) { 6729 if (value_.is(r1)) {
6713 __ Swap(r0, r1, ip); 6730 __ Swap(r0, r1, ip);
6714 } 6731 }
6715 ASSERT(receiver_.is(r2)); 6732 ASSERT(receiver_.is(r2));
6716 6733
6717 // The rest of the instructions in the deferred code must be together. 6734 // The rest of the instructions in the deferred code must be together.
6718 { Assembler::BlockConstPoolScope block_const_pool(masm_); 6735 { Assembler::BlockConstPoolScope block_const_pool(masm_);
6719 // Call keyed store IC. It has the arguments value, key and receiver in r0, 6736 // Call keyed store IC. It has the arguments value, key and receiver in r0,
6720 // r1 and r2. 6737 // r1 and r2.
6721 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 6738 Handle<Code> ic(Builtins::builtin(
6739 (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
6740 : Builtins::KeyedStoreIC_Initialize));
6722 __ Call(ic, RelocInfo::CODE_TARGET); 6741 __ Call(ic, RelocInfo::CODE_TARGET);
6723 // The call must be followed by a nop instruction to indicate that the 6742 // The call must be followed by a nop instruction to indicate that the
6724 // keyed store has been inlined. 6743 // keyed store has been inlined.
6725 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); 6744 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);
6726 6745
6727 // Block the constant pool for one more instruction after leaving this 6746 // Block the constant pool for one more instruction after leaving this
6728 // constant pool block scope to include the branch instruction ending the 6747 // constant pool block scope to include the branch instruction ending the
6729 // deferred code. 6748 // deferred code.
6730 __ BlockConstPoolFor(1); 6749 __ BlockConstPoolFor(1);
6731 } 6750 }
6732 } 6751 }
6733 6752
6734 6753
6735 class DeferredReferenceSetNamedValue: public DeferredCode { 6754 class DeferredReferenceSetNamedValue: public DeferredCode {
6736 public: 6755 public:
6737 DeferredReferenceSetNamedValue(Register value, 6756 DeferredReferenceSetNamedValue(Register value,
6738 Register receiver, 6757 Register receiver,
6739 Handle<String> name) 6758 Handle<String> name,
6740 : value_(value), receiver_(receiver), name_(name) { 6759 StrictModeFlag strict_mode)
6760 : value_(value),
6761 receiver_(receiver),
6762 name_(name),
6763 strict_mode_(strict_mode) {
6741 set_comment("[ DeferredReferenceSetNamedValue"); 6764 set_comment("[ DeferredReferenceSetNamedValue");
6742 } 6765 }
6743 6766
6744 virtual void Generate(); 6767 virtual void Generate();
6745 6768
6746 private: 6769 private:
6747 Register value_; 6770 Register value_;
6748 Register receiver_; 6771 Register receiver_;
6749 Handle<String> name_; 6772 Handle<String> name_;
6773 StrictModeFlag strict_mode_;
6750 }; 6774 };
6751 6775
6752 6776
6753 // Takes value in r0, receiver in r1 and returns the result (the 6777 // Takes value in r0, receiver in r1 and returns the result (the
6754 // value) in r0. 6778 // value) in r0.
6755 void DeferredReferenceSetNamedValue::Generate() { 6779 void DeferredReferenceSetNamedValue::Generate() {
6756 // Record the entry frame and spill. 6780 // Record the entry frame and spill.
6757 VirtualFrame copied_frame(*frame_state()->frame()); 6781 VirtualFrame copied_frame(*frame_state()->frame());
6758 copied_frame.SpillAll(); 6782 copied_frame.SpillAll();
6759 6783
6760 // Ensure value in r0, receiver in r1 to match store ic calling 6784 // Ensure value in r0, receiver in r1 to match store ic calling
6761 // convention. 6785 // convention.
6762 ASSERT(value_.is(r0) && receiver_.is(r1)); 6786 ASSERT(value_.is(r0) && receiver_.is(r1));
6763 __ mov(r2, Operand(name_)); 6787 __ mov(r2, Operand(name_));
6764 6788
6765 // The rest of the instructions in the deferred code must be together. 6789 // The rest of the instructions in the deferred code must be together.
6766 { Assembler::BlockConstPoolScope block_const_pool(masm_); 6790 { Assembler::BlockConstPoolScope block_const_pool(masm_);
6767 // Call keyed store IC. It has the arguments value, key and receiver in r0, 6791 // Call keyed store IC. It has the arguments value, key and receiver in r0,
6768 // r1 and r2. 6792 // r1 and r2.
6769 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 6793 Handle<Code> ic(Builtins::builtin(
6794 (strict_mode_ == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
6795 : Builtins::StoreIC_Initialize));
6770 __ Call(ic, RelocInfo::CODE_TARGET); 6796 __ Call(ic, RelocInfo::CODE_TARGET);
6771 // The call must be followed by a nop instruction to indicate that the 6797 // The call must be followed by a nop instruction to indicate that the
6772 // named store has been inlined. 6798 // named store has been inlined.
6773 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); 6799 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);
6774 6800
6775 // Go back to the frame we entered with. The instructions 6801 // Go back to the frame we entered with. The instructions
6776 // generated by this merge are skipped over by the inline store 6802 // generated by this merge are skipped over by the inline store
6777 // patching mechanism when looking for the branch instruction that 6803 // patching mechanism when looking for the branch instruction that
6778 // tells it where the code to patch is. 6804 // tells it where the code to patch is.
6779 copied_frame.MergeTo(frame_state()->frame()); 6805 copied_frame.MergeTo(frame_state()->frame());
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
6948 // Inline the in-object property case. 6974 // Inline the in-object property case.
6949 JumpTarget slow, done; 6975 JumpTarget slow, done;
6950 6976
6951 // Get the value and receiver from the stack. 6977 // Get the value and receiver from the stack.
6952 frame()->PopToR0(); 6978 frame()->PopToR0();
6953 Register value = r0; 6979 Register value = r0;
6954 frame()->PopToR1(); 6980 frame()->PopToR1();
6955 Register receiver = r1; 6981 Register receiver = r1;
6956 6982
6957 DeferredReferenceSetNamedValue* deferred = 6983 DeferredReferenceSetNamedValue* deferred =
6958 new DeferredReferenceSetNamedValue(value, receiver, name); 6984 new DeferredReferenceSetNamedValue(
6985 value, receiver, name, strict_mode_flag());
6959 6986
6960 // Check that the receiver is a heap object. 6987 // Check that the receiver is a heap object.
6961 __ tst(receiver, Operand(kSmiTagMask)); 6988 __ tst(receiver, Operand(kSmiTagMask));
6962 deferred->Branch(eq); 6989 deferred->Branch(eq);
6963 6990
6964 // The following instructions are the part of the inlined 6991 // The following instructions are the part of the inlined
6965 // in-object property store code which can be patched. Therefore 6992 // in-object property store code which can be patched. Therefore
6966 // the exact number of instructions generated must be fixed, so 6993 // the exact number of instructions generated must be fixed, so
6967 // the constant pool is blocked while generating this code. 6994 // the constant pool is blocked while generating this code.
6968 { Assembler::BlockConstPoolScope block_const_pool(masm_); 6995 { Assembler::BlockConstPoolScope block_const_pool(masm_);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
7119 Register scratch1 = VirtualFrame::scratch0(); 7146 Register scratch1 = VirtualFrame::scratch0();
7120 Register scratch2 = VirtualFrame::scratch1(); 7147 Register scratch2 = VirtualFrame::scratch1();
7121 Register scratch3 = r3; 7148 Register scratch3 = r3;
7122 7149
7123 // Counter will be decremented in the deferred code. Placed here to avoid 7150 // Counter will be decremented in the deferred code. Placed here to avoid
7124 // having it in the instruction stream below where patching will occur. 7151 // having it in the instruction stream below where patching will occur.
7125 __ IncrementCounter(&Counters::keyed_store_inline, 1, 7152 __ IncrementCounter(&Counters::keyed_store_inline, 1,
7126 scratch1, scratch2); 7153 scratch1, scratch2);
7127 7154
7128 7155
7129
7130 // Load the value, key and receiver from the stack. 7156 // Load the value, key and receiver from the stack.
7131 bool value_is_harmless = frame_->KnownSmiAt(0); 7157 bool value_is_harmless = frame_->KnownSmiAt(0);
7132 if (wb_info == NEVER_NEWSPACE) value_is_harmless = true; 7158 if (wb_info == NEVER_NEWSPACE) value_is_harmless = true;
7133 bool key_is_smi = frame_->KnownSmiAt(1); 7159 bool key_is_smi = frame_->KnownSmiAt(1);
7134 Register value = frame_->PopToRegister(); 7160 Register value = frame_->PopToRegister();
7135 Register key = frame_->PopToRegister(value); 7161 Register key = frame_->PopToRegister(value);
7136 VirtualFrame::SpilledScope spilled(frame_); 7162 VirtualFrame::SpilledScope spilled(frame_);
7137 Register receiver = r2; 7163 Register receiver = r2;
7138 frame_->EmitPop(receiver); 7164 frame_->EmitPop(receiver);
7139 7165
7140 #ifdef DEBUG 7166 #ifdef DEBUG
7141 bool we_remembered_the_write_barrier = value_is_harmless; 7167 bool we_remembered_the_write_barrier = value_is_harmless;
7142 #endif 7168 #endif
7143 7169
7144 // The deferred code expects value, key and receiver in registers. 7170 // The deferred code expects value, key and receiver in registers.
7145 DeferredReferenceSetKeyedValue* deferred = 7171 DeferredReferenceSetKeyedValue* deferred =
7146 new DeferredReferenceSetKeyedValue(value, key, receiver); 7172 new DeferredReferenceSetKeyedValue(
7173 value, key, receiver, strict_mode_flag());
7147 7174
7148 // Check that the value is a smi. As this inlined code does not set the 7175 // Check that the value is a smi. As this inlined code does not set the
7149 // write barrier it is only possible to store smi values. 7176 // write barrier it is only possible to store smi values.
7150 if (!value_is_harmless) { 7177 if (!value_is_harmless) {
7151 // If the value is not likely to be a Smi then let's test the fixed array 7178 // If the value is not likely to be a Smi then let's test the fixed array
7152 // for new space instead. See below. 7179 // for new space instead. See below.
7153 if (wb_info == LIKELY_SMI) { 7180 if (wb_info == LIKELY_SMI) {
7154 __ tst(value, Operand(kSmiTagMask)); 7181 __ tst(value, Operand(kSmiTagMask));
7155 deferred->Branch(ne); 7182 deferred->Branch(ne);
7156 #ifdef DEBUG 7183 #ifdef DEBUG
7157 we_remembered_the_write_barrier = true; 7184 we_remembered_the_write_barrier = true;
7158 #endif 7185 #endif
7159 } 7186 }
7160 } 7187 }
7161 7188
7162 if (!key_is_smi) { 7189 if (!key_is_smi) {
7163 // Check that the key is a smi. 7190 // Check that the key is a smi.
7164 __ tst(key, Operand(kSmiTagMask)); 7191 __ tst(key, Operand(kSmiTagMask));
7165 deferred->Branch(ne); 7192 deferred->Branch(ne);
7166 } 7193 }
7167 7194
7168 // Check that the receiver is a heap object. 7195 // Check that the receiver is a heap object.
7169 __ tst(receiver, Operand(kSmiTagMask)); 7196 __ tst(receiver, Operand(kSmiTagMask));
7170 deferred->Branch(eq); 7197 deferred->Branch(eq);
7171 7198
7172 // Check that the receiver is a JSArray. 7199 // Check that the receiver is a JSArray.
7173 __ CompareObjectType(receiver, scratch1, scratch1, JS_ARRAY_TYPE); 7200 __ CompareObjectType(receiver, scratch1, scratch1, JS_ARRAY_TYPE);
7174 deferred->Branch(ne); 7201 deferred->Branch(ne);
7175 7202
7176 // Check that the key is within bounds. Both the key and the length of
7177 // the JSArray are smis. Use unsigned comparison to handle negative keys.
7178 __ ldr(scratch1, FieldMemOperand(receiver, JSArray::kLengthOffset));
7179 __ cmp(scratch1, key);
7180 deferred->Branch(ls); // Unsigned less equal.
7181
7182 // Get the elements array from the receiver. 7203 // Get the elements array from the receiver.
7183 __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset)); 7204 __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset));
7184 if (!value_is_harmless && wb_info != LIKELY_SMI) { 7205 if (!value_is_harmless && wb_info != LIKELY_SMI) {
7185 Label ok; 7206 Label ok;
7186 __ and_(scratch2, scratch1, Operand(ExternalReference::new_space_mask())); 7207 __ and_(scratch2, scratch1, Operand(ExternalReference::new_space_mask()));
7187 __ cmp(scratch2, Operand(ExternalReference::new_space_start())); 7208 __ cmp(scratch2, Operand(ExternalReference::new_space_start()));
7188 __ tst(value, Operand(kSmiTagMask), ne); 7209 __ tst(value, Operand(kSmiTagMask), ne);
7189 deferred->Branch(ne); 7210 deferred->Branch(ne);
7190 #ifdef DEBUG 7211 #ifdef DEBUG
7191 we_remembered_the_write_barrier = true; 7212 we_remembered_the_write_barrier = true;
7192 #endif 7213 #endif
7193 } 7214 }
7194 // Check that the elements array is not a dictionary. 7215 // Check that the elements array is not a dictionary.
7195 __ ldr(scratch2, FieldMemOperand(scratch1, JSObject::kMapOffset)); 7216 __ ldr(scratch2, FieldMemOperand(scratch1, JSObject::kMapOffset));
7217
7196 // The following instructions are the part of the inlined store keyed 7218 // The following instructions are the part of the inlined store keyed
7197 // property code which can be patched. Therefore the exact number of 7219 // property code which can be patched. Therefore the exact number of
7198 // instructions generated need to be fixed, so the constant pool is blocked 7220 // instructions generated need to be fixed, so the constant pool is blocked
7199 // while generating this code. 7221 // while generating this code.
7200 { Assembler::BlockConstPoolScope block_const_pool(masm_); 7222 { Assembler::BlockConstPoolScope block_const_pool(masm_);
7201 #ifdef DEBUG 7223 #ifdef DEBUG
7202 Label check_inlined_codesize; 7224 Label check_inlined_codesize;
7203 masm_->bind(&check_inlined_codesize); 7225 masm_->bind(&check_inlined_codesize);
7204 #endif 7226 #endif
7205 7227
7206 // Read the fixed array map from the constant pool (not from the root 7228 // Read the fixed array map from the constant pool (not from the root
7207 // array) so that the value can be patched. When debugging, we patch this 7229 // array) so that the value can be patched. When debugging, we patch this
7208 // comparison to always fail so that we will hit the IC call in the 7230 // comparison to always fail so that we will hit the IC call in the
7209 // deferred code which will allow the debugger to break for fast case 7231 // deferred code which will allow the debugger to break for fast case
7210 // stores. 7232 // stores.
7211 __ mov(scratch3, Operand(Factory::fixed_array_map())); 7233 __ mov(scratch3, Operand(Factory::fixed_array_map()));
7212 __ cmp(scratch2, scratch3); 7234 __ cmp(scratch2, scratch3);
7213 deferred->Branch(ne); 7235 deferred->Branch(ne);
7214 7236
7237 // Check that the key is within bounds. Both the key and the length of
7238 // the JSArray are smis (because the fixed array check above ensures the
7239 // elements are in fast case). Use unsigned comparison to handle negative
7240 // keys.
7241 __ ldr(scratch3, FieldMemOperand(receiver, JSArray::kLengthOffset));
7242 __ cmp(scratch3, key);
7243 deferred->Branch(ls); // Unsigned less equal.
7244
7215 // Store the value. 7245 // Store the value.
7216 __ add(scratch1, scratch1, 7246 __ add(scratch1, scratch1,
7217 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 7247 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
7218 __ str(value, 7248 __ str(value,
7219 MemOperand(scratch1, key, LSL, 7249 MemOperand(scratch1, key, LSL,
7220 kPointerSizeLog2 - (kSmiTagSize + kSmiShiftSize))); 7250 kPointerSizeLog2 - (kSmiTagSize + kSmiShiftSize)));
7221 7251
7222 // Make sure that the expected number of instructions are generated. 7252 // Make sure that the expected number of instructions are generated.
7223 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch, 7253 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch,
7224 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); 7254 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
7225 } 7255 }
7226 7256
7227 ASSERT(we_remembered_the_write_barrier); 7257 ASSERT(we_remembered_the_write_barrier);
7228 7258
7229 deferred->BindExit(); 7259 deferred->BindExit();
7230 } else { 7260 } else {
7231 frame()->CallKeyedStoreIC(); 7261 frame()->CallKeyedStoreIC(strict_mode_flag());
7232 } 7262 }
7233 } 7263 }
7234 7264
7235 7265
7236 #ifdef DEBUG 7266 #ifdef DEBUG
7237 bool CodeGenerator::HasValidEntryRegisters() { return true; } 7267 bool CodeGenerator::HasValidEntryRegisters() { return true; }
7238 #endif 7268 #endif
7239 7269
7240 7270
7241 #undef __ 7271 #undef __
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
7389 BinaryOpIC::GetName(runtime_operands_type_)); 7419 BinaryOpIC::GetName(runtime_operands_type_));
7390 return name_; 7420 return name_;
7391 } 7421 }
7392 7422
7393 7423
7394 #undef __ 7424 #undef __
7395 7425
7396 } } // namespace v8::internal 7426 } } // namespace v8::internal
7397 7427
7398 #endif // V8_TARGET_ARCH_ARM 7428 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/constants-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698