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

Side by Side Diff: src/ia32/codegen-ia32.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/ia32/code-stubs-ia32.cc ('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 715 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 LoadFromSlotCheckForArguments(variable->AsSlot(), INSIDE_TYPEOF); 726 LoadFromSlotCheckForArguments(variable->AsSlot(), INSIDE_TYPEOF);
727 } else { 727 } else {
728 // Anything else can be handled normally. 728 // Anything else can be handled normally.
729 Load(expr); 729 Load(expr);
730 } 730 }
731 } 731 }
732 732
733 733
734 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { 734 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
735 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; 735 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
736 ASSERT(scope()->arguments_shadow() != NULL); 736
737 // In strict mode there is no need for shadow arguments.
738 ASSERT(scope()->arguments_shadow() != NULL || scope()->is_strict_mode());
739
737 // We don't want to do lazy arguments allocation for functions that 740 // We don't want to do lazy arguments allocation for functions that
738 // have heap-allocated contexts, because it interfers with the 741 // have heap-allocated contexts, because it interfers with the
739 // uninitialized const tracking in the context objects. 742 // uninitialized const tracking in the context objects.
740 return (scope()->num_heap_slots() > 0) 743 return (scope()->num_heap_slots() > 0 || scope()->is_strict_mode())
741 ? EAGER_ARGUMENTS_ALLOCATION 744 ? EAGER_ARGUMENTS_ALLOCATION
742 : LAZY_ARGUMENTS_ALLOCATION; 745 : LAZY_ARGUMENTS_ALLOCATION;
743 } 746 }
744 747
745 748
746 Result CodeGenerator::StoreArgumentsObject(bool initial) { 749 Result CodeGenerator::StoreArgumentsObject(bool initial) {
747 ArgumentsAllocationMode mode = ArgumentsMode(); 750 ArgumentsAllocationMode mode = ArgumentsMode();
748 ASSERT(mode != NO_ARGUMENTS_ALLOCATION); 751 ASSERT(mode != NO_ARGUMENTS_ALLOCATION);
749 752
750 Comment cmnt(masm_, "[ store arguments object"); 753 Comment cmnt(masm_, "[ store arguments object");
751 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) { 754 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) {
752 // When using lazy arguments allocation, we store the arguments marker value 755 // When using lazy arguments allocation, we store the arguments marker value
753 // as a sentinel indicating that the arguments object hasn't been 756 // as a sentinel indicating that the arguments object hasn't been
754 // allocated yet. 757 // allocated yet.
755 frame_->Push(Factory::arguments_marker()); 758 frame_->Push(Factory::arguments_marker());
756 } else { 759 } else {
757 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 760 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
758 frame_->PushFunction(); 761 frame_->PushFunction();
759 frame_->PushReceiverSlotAddress(); 762 frame_->PushReceiverSlotAddress();
760 frame_->Push(Smi::FromInt(scope()->num_parameters())); 763 frame_->Push(Smi::FromInt(scope()->num_parameters()));
761 Result result = frame_->CallStub(&stub, 3); 764 Result result = frame_->CallStub(&stub, 3);
762 frame_->Push(&result); 765 frame_->Push(&result);
763 } 766 }
764 767
765 Variable* arguments = scope()->arguments(); 768 Variable* arguments = scope()->arguments();
766 Variable* shadow = scope()->arguments_shadow(); 769 Variable* shadow = scope()->arguments_shadow();
770
767 ASSERT(arguments != NULL && arguments->AsSlot() != NULL); 771 ASSERT(arguments != NULL && arguments->AsSlot() != NULL);
768 ASSERT(shadow != NULL && shadow->AsSlot() != NULL); 772 ASSERT((shadow != NULL && shadow->AsSlot() != NULL) ||
773 scope()->is_strict_mode());
774
769 JumpTarget done; 775 JumpTarget done;
770 bool skip_arguments = false; 776 bool skip_arguments = false;
771 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { 777 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
772 // We have to skip storing into the arguments slot if it has 778 // We have to skip storing into the arguments slot if it has
773 // already been written to. This can happen if the a function 779 // already been written to. This can happen if the a function
774 // has a local variable named 'arguments'. 780 // has a local variable named 'arguments'.
775 LoadFromSlot(arguments->AsSlot(), NOT_INSIDE_TYPEOF); 781 LoadFromSlot(arguments->AsSlot(), NOT_INSIDE_TYPEOF);
776 Result probe = frame_->Pop(); 782 Result probe = frame_->Pop();
777 if (probe.is_constant()) { 783 if (probe.is_constant()) {
778 // We have to skip updating the arguments object if it has 784 // We have to skip updating the arguments object if it has
779 // been assigned a proper value. 785 // been assigned a proper value.
780 skip_arguments = !probe.handle()->IsArgumentsMarker(); 786 skip_arguments = !probe.handle()->IsArgumentsMarker();
781 } else { 787 } else {
782 __ cmp(Operand(probe.reg()), Immediate(Factory::arguments_marker())); 788 __ cmp(Operand(probe.reg()), Immediate(Factory::arguments_marker()));
783 probe.Unuse(); 789 probe.Unuse();
784 done.Branch(not_equal); 790 done.Branch(not_equal);
785 } 791 }
786 } 792 }
787 if (!skip_arguments) { 793 if (!skip_arguments) {
788 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT); 794 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT);
789 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); 795 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
790 } 796 }
791 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT); 797 if (shadow != NULL) {
798 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
799 }
792 return frame_->Pop(); 800 return frame_->Pop();
793 } 801 }
794 802
795 //------------------------------------------------------------------------------ 803 //------------------------------------------------------------------------------
796 // CodeGenerator implementation of variables, lookups, and stores. 804 // CodeGenerator implementation of variables, lookups, and stores.
797 805
798 Reference::Reference(CodeGenerator* cgen, 806 Reference::Reference(CodeGenerator* cgen,
799 Expression* expression, 807 Expression* expression,
800 bool persist_after_get) 808 bool persist_after_get)
801 : cgen_(cgen), 809 : cgen_(cgen),
(...skipping 2721 matching lines...) Expand 10 before | Expand all | Expand 10 after
3523 3531
3524 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 3532 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
3525 // Call the runtime to declare the globals. The inevitable call 3533 // Call the runtime to declare the globals. The inevitable call
3526 // will sync frame elements to memory anyway, so we do it eagerly to 3534 // will sync frame elements to memory anyway, so we do it eagerly to
3527 // allow us to push the arguments directly into place. 3535 // allow us to push the arguments directly into place.
3528 frame_->SyncRange(0, frame_->element_count() - 1); 3536 frame_->SyncRange(0, frame_->element_count() - 1);
3529 3537
3530 frame_->EmitPush(esi); // The context is the first argument. 3538 frame_->EmitPush(esi); // The context is the first argument.
3531 frame_->EmitPush(Immediate(pairs)); 3539 frame_->EmitPush(Immediate(pairs));
3532 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 3540 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
3533 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 3541 frame_->EmitPush(Immediate(Smi::FromInt(strict_mode_flag())));
3542 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 4);
3534 // Return value is ignored. 3543 // Return value is ignored.
3535 } 3544 }
3536 3545
3537 3546
3538 void CodeGenerator::VisitDeclaration(Declaration* node) { 3547 void CodeGenerator::VisitDeclaration(Declaration* node) {
3539 Comment cmnt(masm_, "[ Declaration"); 3548 Comment cmnt(masm_, "[ Declaration");
3540 Variable* var = node->proxy()->var(); 3549 Variable* var = node->proxy()->var();
3541 ASSERT(var != NULL); // must have been resolved 3550 ASSERT(var != NULL); // must have been resolved
3542 Slot* slot = var->AsSlot(); 3551 Slot* slot = var->AsSlot();
3543 3552
(...skipping 1712 matching lines...) Expand 10 before | Expand all | Expand 10 after
5256 // context slot declaration, but we cannot initialize it at the same 5265 // context slot declaration, but we cannot initialize it at the same
5257 // time, because the const declaration may be at the end of the eval 5266 // time, because the const declaration may be at the end of the eval
5258 // code (sigh...) and the const variable may have been used before 5267 // code (sigh...) and the const variable may have been used before
5259 // (where its value is 'undefined'). Thus, we can only do the 5268 // (where its value is 'undefined'). Thus, we can only do the
5260 // initialization when we actually encounter the expression and when 5269 // initialization when we actually encounter the expression and when
5261 // the expression operands are defined and valid, and thus we need the 5270 // the expression operands are defined and valid, and thus we need the
5262 // split into 2 operations: declaration of the context slot followed 5271 // split into 2 operations: declaration of the context slot followed
5263 // by initialization. 5272 // by initialization.
5264 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); 5273 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
5265 } else { 5274 } else {
5266 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3); 5275 frame_->Push(Smi::FromInt(strict_mode_flag()));
5276 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
5267 } 5277 }
5268 // Storing a variable must keep the (new) value on the expression 5278 // Storing a variable must keep the (new) value on the expression
5269 // stack. This is necessary for compiling chained assignment 5279 // stack. This is necessary for compiling chained assignment
5270 // expressions. 5280 // expressions.
5271 frame_->Push(&value); 5281 frame_->Push(&value);
5272 5282
5273 } else { 5283 } else {
5274 ASSERT(!slot->var()->is_dynamic()); 5284 ASSERT(!slot->var()->is_dynamic());
5275 5285
5276 JumpTarget exit; 5286 JumpTarget exit;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
5362 ASSERT(var->is_global()); 5372 ASSERT(var->is_global());
5363 ASSERT(!in_safe_int32_mode()); 5373 ASSERT(!in_safe_int32_mode());
5364 Reference ref(this, node); 5374 Reference ref(this, node);
5365 ref.GetValue(); 5375 ref.GetValue();
5366 } 5376 }
5367 } 5377 }
5368 5378
5369 5379
5370 void CodeGenerator::VisitLiteral(Literal* node) { 5380 void CodeGenerator::VisitLiteral(Literal* node) {
5371 Comment cmnt(masm_, "[ Literal"); 5381 Comment cmnt(masm_, "[ Literal");
5372 if (in_safe_int32_mode()) { 5382 if (frame_->ConstantPoolOverflowed()) {
5373 frame_->PushUntaggedElement(node->handle()); 5383 Result temp = allocator_->Allocate();
5384 ASSERT(temp.is_valid());
5385 if (in_safe_int32_mode()) {
5386 temp.set_untagged_int32(true);
5387 }
5388 __ Set(temp.reg(), Immediate(node->handle()));
5389 frame_->Push(&temp);
5374 } else { 5390 } else {
5375 frame_->Push(node->handle()); 5391 if (in_safe_int32_mode()) {
5392 frame_->PushUntaggedElement(node->handle());
5393 } else {
5394 frame_->Push(node->handle());
5395 }
5376 } 5396 }
5377 } 5397 }
5378 5398
5379 5399
5380 void CodeGenerator::PushUnsafeSmi(Handle<Object> value) { 5400 void CodeGenerator::PushUnsafeSmi(Handle<Object> value) {
5381 ASSERT(value->IsSmi()); 5401 ASSERT(value->IsSmi());
5382 int bits = reinterpret_cast<int>(*value); 5402 int bits = reinterpret_cast<int>(*value);
5383 __ push(Immediate(bits ^ jit_cookie_)); 5403 __ push(Immediate(bits ^ jit_cookie_));
5384 __ xor_(Operand(esp, 0), Immediate(jit_cookie_)); 5404 __ xor_(Operand(esp, 0), Immediate(jit_cookie_));
5385 } 5405 }
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
5610 break; 5630 break;
5611 } 5631 }
5612 // Fall through 5632 // Fall through
5613 } 5633 }
5614 case ObjectLiteral::Property::PROTOTYPE: { 5634 case ObjectLiteral::Property::PROTOTYPE: {
5615 // Duplicate the object as an argument to the runtime call. 5635 // Duplicate the object as an argument to the runtime call.
5616 frame_->Dup(); 5636 frame_->Dup();
5617 Load(property->key()); 5637 Load(property->key());
5618 Load(property->value()); 5638 Load(property->value());
5619 if (property->emit_store()) { 5639 if (property->emit_store()) {
5640 frame_->Push(Smi::FromInt(NONE)); // PropertyAttributes
5620 // Ignore the result. 5641 // Ignore the result.
5621 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3); 5642 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4);
5622 } else { 5643 } else {
5623 frame_->Drop(3); 5644 frame_->Drop(3);
5624 } 5645 }
5625 break; 5646 break;
5626 } 5647 }
5627 case ObjectLiteral::Property::SETTER: { 5648 case ObjectLiteral::Property::SETTER: {
5628 // Duplicate the object as an argument to the runtime call. 5649 // Duplicate the object as an argument to the runtime call.
5629 frame_->Dup(); 5650 frame_->Dup();
5630 Load(property->key()); 5651 Load(property->key());
5631 frame_->Push(Smi::FromInt(1)); 5652 frame_->Push(Smi::FromInt(1));
(...skipping 2610 matching lines...) Expand 10 before | Expand all | Expand 10 after
8242 Load(property->key()); 8263 Load(property->key());
8243 frame_->Push(Smi::FromInt(strict_mode_flag())); 8264 frame_->Push(Smi::FromInt(strict_mode_flag()));
8244 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3); 8265 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3);
8245 frame_->Push(&answer); 8266 frame_->Push(&answer);
8246 return; 8267 return;
8247 } 8268 }
8248 8269
8249 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); 8270 Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
8250 if (variable != NULL) { 8271 if (variable != NULL) {
8251 // Delete of an unqualified identifier is disallowed in strict mode 8272 // Delete of an unqualified identifier is disallowed in strict mode
8252 // so this code can only be reached in non-strict mode. 8273 // but "delete this" is.
8253 ASSERT(strict_mode_flag() == kNonStrictMode); 8274 ASSERT(strict_mode_flag() == kNonStrictMode || variable->is_this());
8254 Slot* slot = variable->AsSlot(); 8275 Slot* slot = variable->AsSlot();
8255 if (variable->is_global()) { 8276 if (variable->is_global()) {
8256 LoadGlobal(); 8277 LoadGlobal();
8257 frame_->Push(variable->name()); 8278 frame_->Push(variable->name());
8258 frame_->Push(Smi::FromInt(kNonStrictMode)); 8279 frame_->Push(Smi::FromInt(kNonStrictMode));
8259 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, 8280 Result answer = frame_->InvokeBuiltin(Builtins::DELETE,
8260 CALL_FUNCTION, 3); 8281 CALL_FUNCTION, 3);
8261 frame_->Push(&answer); 8282 frame_->Push(&answer);
8262 return;
8263 8283
8264 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 8284 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
8265 // Call the runtime to delete from the context holding the named 8285 // Call the runtime to delete from the context holding the named
8266 // variable. Sync the virtual frame eagerly so we can push the 8286 // variable. Sync the virtual frame eagerly so we can push the
8267 // arguments directly into place. 8287 // arguments directly into place.
8268 frame_->SyncRange(0, frame_->element_count() - 1); 8288 frame_->SyncRange(0, frame_->element_count() - 1);
8269 frame_->EmitPush(esi); 8289 frame_->EmitPush(esi);
8270 frame_->EmitPush(Immediate(variable->name())); 8290 frame_->EmitPush(Immediate(variable->name()));
8271 Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2); 8291 Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2);
8272 frame_->Push(&answer); 8292 frame_->Push(&answer);
8273 return; 8293 } else {
8294 // Default: Result of deleting non-global, not dynamically
8295 // introduced variables is false.
8296 frame_->Push(Factory::false_value());
8274 } 8297 }
8275
8276 // Default: Result of deleting non-global, not dynamically
8277 // introduced variables is false.
8278 frame_->Push(Factory::false_value());
8279
8280 } else { 8298 } else {
8281 // Default: Result of deleting expressions is true. 8299 // Default: Result of deleting expressions is true.
8282 Load(node->expression()); // may have side-effects 8300 Load(node->expression()); // may have side-effects
8283 frame_->SetElementAt(0, Factory::true_value()); 8301 frame_->SetElementAt(0, Factory::true_value());
8284 } 8302 }
8285 8303
8286 } else if (op == Token::TYPEOF) { 8304 } else if (op == Token::TYPEOF) {
8287 // Special case for loading the typeof expression; see comment on 8305 // Special case for loading the typeof expression; see comment on
8288 // LoadTypeofExpression(). 8306 // LoadTypeofExpression().
8289 LoadTypeofExpression(node->expression()); 8307 LoadTypeofExpression(node->expression());
(...skipping 21 matching lines...) Expand all
8311 if (in_safe_int32_mode()) { 8329 if (in_safe_int32_mode()) {
8312 Visit(node->expression()); 8330 Visit(node->expression());
8313 Result value = frame_->Pop(); 8331 Result value = frame_->Pop();
8314 ASSERT(value.is_untagged_int32()); 8332 ASSERT(value.is_untagged_int32());
8315 // Registers containing an int32 value are not multiply used. 8333 // Registers containing an int32 value are not multiply used.
8316 ASSERT(!value.is_register() || !frame_->is_used(value.reg())); 8334 ASSERT(!value.is_register() || !frame_->is_used(value.reg()));
8317 value.ToRegister(); 8335 value.ToRegister();
8318 switch (op) { 8336 switch (op) {
8319 case Token::SUB: { 8337 case Token::SUB: {
8320 __ neg(value.reg()); 8338 __ neg(value.reg());
8339 frame_->Push(&value);
8321 if (node->no_negative_zero()) { 8340 if (node->no_negative_zero()) {
8322 // -MIN_INT is MIN_INT with the overflow flag set. 8341 // -MIN_INT is MIN_INT with the overflow flag set.
8323 unsafe_bailout_->Branch(overflow); 8342 unsafe_bailout_->Branch(overflow);
8324 } else { 8343 } else {
8325 // MIN_INT and 0 both have bad negations. They both have 31 zeros. 8344 // MIN_INT and 0 both have bad negations. They both have 31 zeros.
8326 __ test(value.reg(), Immediate(0x7FFFFFFF)); 8345 __ test(value.reg(), Immediate(0x7FFFFFFF));
8327 unsafe_bailout_->Branch(zero); 8346 unsafe_bailout_->Branch(zero);
8328 } 8347 }
8329 break; 8348 break;
8330 } 8349 }
8331 case Token::BIT_NOT: { 8350 case Token::BIT_NOT: {
8332 __ not_(value.reg()); 8351 __ not_(value.reg());
8352 frame_->Push(&value);
8333 break; 8353 break;
8334 } 8354 }
8335 case Token::ADD: { 8355 case Token::ADD: {
8336 // Unary plus has no effect on int32 values. 8356 // Unary plus has no effect on int32 values.
8357 frame_->Push(&value);
8337 break; 8358 break;
8338 } 8359 }
8339 default: 8360 default:
8340 UNREACHABLE(); 8361 UNREACHABLE();
8341 break; 8362 break;
8342 } 8363 }
8343 frame_->Push(&value);
8344 } else { 8364 } else {
8345 Load(node->expression()); 8365 Load(node->expression());
8346 bool can_overwrite = node->expression()->ResultOverwriteAllowed(); 8366 bool can_overwrite = node->expression()->ResultOverwriteAllowed();
8347 UnaryOverwriteMode overwrite = 8367 UnaryOverwriteMode overwrite =
8348 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 8368 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
8349 bool no_negative_zero = node->expression()->no_negative_zero(); 8369 bool no_negative_zero = node->expression()->no_negative_zero();
8350 switch (op) { 8370 switch (op) {
8351 case Token::NOT: 8371 case Token::NOT:
8352 case Token::DELETE: 8372 case Token::DELETE:
8353 case Token::TYPEOF: 8373 case Token::TYPEOF:
(...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after
9469 9489
9470 if (!dst_.is(eax)) __ mov(dst_, eax); 9490 if (!dst_.is(eax)) __ mov(dst_, eax);
9471 } 9491 }
9472 9492
9473 9493
9474 class DeferredReferenceSetKeyedValue: public DeferredCode { 9494 class DeferredReferenceSetKeyedValue: public DeferredCode {
9475 public: 9495 public:
9476 DeferredReferenceSetKeyedValue(Register value, 9496 DeferredReferenceSetKeyedValue(Register value,
9477 Register key, 9497 Register key,
9478 Register receiver, 9498 Register receiver,
9479 Register scratch) 9499 Register scratch,
9500 StrictModeFlag strict_mode)
9480 : value_(value), 9501 : value_(value),
9481 key_(key), 9502 key_(key),
9482 receiver_(receiver), 9503 receiver_(receiver),
9483 scratch_(scratch) { 9504 scratch_(scratch),
9505 strict_mode_(strict_mode) {
9484 set_comment("[ DeferredReferenceSetKeyedValue"); 9506 set_comment("[ DeferredReferenceSetKeyedValue");
9485 } 9507 }
9486 9508
9487 virtual void Generate(); 9509 virtual void Generate();
9488 9510
9489 Label* patch_site() { return &patch_site_; } 9511 Label* patch_site() { return &patch_site_; }
9490 9512
9491 private: 9513 private:
9492 Register value_; 9514 Register value_;
9493 Register key_; 9515 Register key_;
9494 Register receiver_; 9516 Register receiver_;
9495 Register scratch_; 9517 Register scratch_;
9496 Label patch_site_; 9518 Label patch_site_;
9519 StrictModeFlag strict_mode_;
9497 }; 9520 };
9498 9521
9499 9522
9500 void DeferredReferenceSetKeyedValue::Generate() { 9523 void DeferredReferenceSetKeyedValue::Generate() {
9501 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); 9524 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1);
9502 // Move value_ to eax, key_ to ecx, and receiver_ to edx. 9525 // Move value_ to eax, key_ to ecx, and receiver_ to edx.
9503 Register old_value = value_; 9526 Register old_value = value_;
9504 9527
9505 // First, move value to eax. 9528 // First, move value to eax.
9506 if (!value_.is(eax)) { 9529 if (!value_.is(eax)) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
9545 } 9568 }
9546 } 9569 }
9547 } else { // Key is not in edx or ecx. 9570 } else { // Key is not in edx or ecx.
9548 if (!receiver_.is(edx)) { 9571 if (!receiver_.is(edx)) {
9549 __ mov(edx, receiver_); 9572 __ mov(edx, receiver_);
9550 } 9573 }
9551 __ mov(ecx, key_); 9574 __ mov(ecx, key_);
9552 } 9575 }
9553 9576
9554 // Call the IC stub. 9577 // Call the IC stub.
9555 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 9578 Handle<Code> ic(Builtins::builtin(
9579 (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
9580 : Builtins::KeyedStoreIC_Initialize));
9556 __ call(ic, RelocInfo::CODE_TARGET); 9581 __ call(ic, RelocInfo::CODE_TARGET);
9557 // The delta from the start of the map-compare instruction to the 9582 // The delta from the start of the map-compare instruction to the
9558 // test instruction. We use masm_-> directly here instead of the 9583 // test instruction. We use masm_-> directly here instead of the
9559 // __ macro because the macro sometimes uses macro expansion to turn 9584 // __ macro because the macro sometimes uses macro expansion to turn
9560 // into something that can't return a value. This is encountered 9585 // into something that can't return a value. This is encountered
9561 // when doing generated code coverage tests. 9586 // when doing generated code coverage tests.
9562 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 9587 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
9563 // Here we use masm_-> instead of the __ macro because this is the 9588 // Here we use masm_-> instead of the __ macro because this is the
9564 // instruction that gets patched and coverage code gets in the way. 9589 // instruction that gets patched and coverage code gets in the way.
9565 masm_->test(eax, Immediate(-delta_to_patch_site)); 9590 masm_->test(eax, Immediate(-delta_to_patch_site));
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
9910 9935
9911 // Make sure that value, key and receiver are in registers. 9936 // Make sure that value, key and receiver are in registers.
9912 result.ToRegister(); 9937 result.ToRegister();
9913 key.ToRegister(); 9938 key.ToRegister();
9914 receiver.ToRegister(); 9939 receiver.ToRegister();
9915 9940
9916 DeferredReferenceSetKeyedValue* deferred = 9941 DeferredReferenceSetKeyedValue* deferred =
9917 new DeferredReferenceSetKeyedValue(result.reg(), 9942 new DeferredReferenceSetKeyedValue(result.reg(),
9918 key.reg(), 9943 key.reg(),
9919 receiver.reg(), 9944 receiver.reg(),
9920 tmp.reg()); 9945 tmp.reg(),
9946 strict_mode_flag());
9921 9947
9922 // Check that the receiver is not a smi. 9948 // Check that the receiver is not a smi.
9923 __ test(receiver.reg(), Immediate(kSmiTagMask)); 9949 __ test(receiver.reg(), Immediate(kSmiTagMask));
9924 deferred->Branch(zero); 9950 deferred->Branch(zero);
9925 9951
9926 // Check that the key is a smi. 9952 // Check that the key is a smi.
9927 if (!key.is_smi()) { 9953 if (!key.is_smi()) {
9928 __ test(key.reg(), Immediate(kSmiTagMask)); 9954 __ test(key.reg(), Immediate(kSmiTagMask));
9929 deferred->Branch(not_zero); 9955 deferred->Branch(not_zero);
9930 } else { 9956 } else {
9931 if (FLAG_debug_code) __ AbortIfNotSmi(key.reg()); 9957 if (FLAG_debug_code) __ AbortIfNotSmi(key.reg());
9932 } 9958 }
9933 9959
9934 // Check that the receiver is a JSArray. 9960 // Check that the receiver is a JSArray.
9935 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, tmp.reg()); 9961 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, tmp.reg());
9936 deferred->Branch(not_equal); 9962 deferred->Branch(not_equal);
9937 9963
9938 // Check that the key is within bounds. Both the key and the length of
9939 // the JSArray are smis. Use unsigned comparison to handle negative keys.
9940 __ cmp(key.reg(),
9941 FieldOperand(receiver.reg(), JSArray::kLengthOffset));
9942 deferred->Branch(above_equal);
9943
9944 // Get the elements array from the receiver and check that it is not a 9964 // Get the elements array from the receiver and check that it is not a
9945 // dictionary. 9965 // dictionary.
9946 __ mov(tmp.reg(), 9966 __ mov(tmp.reg(),
9947 FieldOperand(receiver.reg(), JSArray::kElementsOffset)); 9967 FieldOperand(receiver.reg(), JSArray::kElementsOffset));
9948 9968
9949 // Check whether it is possible to omit the write barrier. If the elements 9969 // Check whether it is possible to omit the write barrier. If the elements
9950 // array is in new space or the value written is a smi we can safely update 9970 // array is in new space or the value written is a smi we can safely update
9951 // the elements array without write barrier. 9971 // the elements array without write barrier.
9952 Label in_new_space; 9972 Label in_new_space;
9953 __ InNewSpace(tmp.reg(), tmp2.reg(), equal, &in_new_space); 9973 __ InNewSpace(tmp.reg(), tmp2.reg(), equal, &in_new_space);
9954 if (!value_is_constant) { 9974 if (!value_is_constant) {
9955 __ test(result.reg(), Immediate(kSmiTagMask)); 9975 __ test(result.reg(), Immediate(kSmiTagMask));
9956 deferred->Branch(not_zero); 9976 deferred->Branch(not_zero);
9957 } 9977 }
9958 9978
9959 9979
9960 __ bind(&in_new_space); 9980 __ bind(&in_new_space);
9961 // Bind the deferred code patch site to be able to locate the fixed 9981 // Bind the deferred code patch site to be able to locate the fixed
9962 // array map comparison. When debugging, we patch this comparison to 9982 // array map comparison. When debugging, we patch this comparison to
9963 // always fail so that we will hit the IC call in the deferred code 9983 // always fail so that we will hit the IC call in the deferred code
9964 // which will allow the debugger to break for fast case stores. 9984 // which will allow the debugger to break for fast case stores.
9965 __ bind(deferred->patch_site()); 9985 __ bind(deferred->patch_site());
9966 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset), 9986 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
9967 Immediate(Factory::fixed_array_map())); 9987 Immediate(Factory::fixed_array_map()));
9968 deferred->Branch(not_equal); 9988 deferred->Branch(not_equal);
9969 9989
9990 // Check that the key is within bounds. Both the key and the length of
9991 // the JSArray are smis (because the fixed array check above ensures the
9992 // elements are in fast case). Use unsigned comparison to handle negative
9993 // keys.
9994 __ cmp(key.reg(),
9995 FieldOperand(receiver.reg(), JSArray::kLengthOffset));
9996 deferred->Branch(above_equal);
9997
9970 // Store the value. 9998 // Store the value.
9971 __ mov(FixedArrayElementOperand(tmp.reg(), key.reg()), result.reg()); 9999 __ mov(FixedArrayElementOperand(tmp.reg(), key.reg()), result.reg());
9972 __ IncrementCounter(&Counters::keyed_store_inline, 1); 10000 __ IncrementCounter(&Counters::keyed_store_inline, 1);
9973 10001
9974 deferred->BindExit(); 10002 deferred->BindExit();
9975 } else { 10003 } else {
9976 result = frame()->CallKeyedStoreIC(); 10004 result = frame()->CallKeyedStoreIC(strict_mode_flag());
9977 // Make sure that we do not have a test instruction after the 10005 // Make sure that we do not have a test instruction after the
9978 // call. A test instruction after the call is used to 10006 // call. A test instruction after the call is used to
9979 // indicate that we have generated an inline version of the 10007 // indicate that we have generated an inline version of the
9980 // keyed store. 10008 // keyed store.
9981 __ nop(); 10009 __ nop();
9982 } 10010 }
9983 ASSERT(frame()->height() == original_height - 3); 10011 ASSERT(frame()->height() == original_height - 3);
9984 return result; 10012 return result;
9985 } 10013 }
9986 10014
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
10349 memcpy(base, desc.buffer, desc.instr_size); 10377 memcpy(base, desc.buffer, desc.instr_size);
10350 CPU::FlushICache(base, desc.instr_size); 10378 CPU::FlushICache(base, desc.instr_size);
10351 return FUNCTION_CAST<MemCopyFunction>(reinterpret_cast<Address>(base)); 10379 return FUNCTION_CAST<MemCopyFunction>(reinterpret_cast<Address>(base));
10352 } 10380 }
10353 10381
10354 #undef __ 10382 #undef __
10355 10383
10356 } } // namespace v8::internal 10384 } } // namespace v8::internal
10357 10385
10358 #endif // V8_TARGET_ARCH_IA32 10386 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.cc ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698