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

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

Issue 2833048: ARM: Don't emit a write barrier for an inlined keyed load... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 5 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') | no next file » | 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 1727 matching lines...) Expand 10 before | Expand all | Expand 10 after
1738 ASSERT(!var->is_global()); 1738 ASSERT(!var->is_global());
1739 1739
1740 // If we have a function or a constant, we need to initialize the variable. 1740 // If we have a function or a constant, we need to initialize the variable.
1741 Expression* val = NULL; 1741 Expression* val = NULL;
1742 if (node->mode() == Variable::CONST) { 1742 if (node->mode() == Variable::CONST) {
1743 val = new Literal(Factory::the_hole_value()); 1743 val = new Literal(Factory::the_hole_value());
1744 } else { 1744 } else {
1745 val = node->fun(); // NULL if we don't have a function 1745 val = node->fun(); // NULL if we don't have a function
1746 } 1746 }
1747 1747
1748
1748 if (val != NULL) { 1749 if (val != NULL) {
1750 WriteBarrierCharacter wb_info =
1751 val->type()->IsLikelySmi() ? LIKELY_SMI : UNLIKELY_SMI;
1752 if (val->AsLiteral() != NULL) wb_info = NEVER_NEWSPACE;
1749 // Set initial value. 1753 // Set initial value.
1750 Reference target(this, node->proxy()); 1754 Reference target(this, node->proxy());
1751 Load(val); 1755 Load(val);
1752 target.SetValue(NOT_CONST_INIT); 1756 target.SetValue(NOT_CONST_INIT, wb_info);
1753 1757
1754 // Get rid of the assigned value (declarations are statements). 1758 // Get rid of the assigned value (declarations are statements).
1755 frame_->Drop(); 1759 frame_->Drop();
1756 } 1760 }
1757 ASSERT(frame_->height() == original_height); 1761 ASSERT(frame_->height() == original_height);
1758 } 1762 }
1759 1763
1760 1764
1761 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { 1765 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
1762 #ifdef DEBUG 1766 #ifdef DEBUG
(...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after
2478 2482
2479 end_del_check.Bind(); 2483 end_del_check.Bind();
2480 // Store the entry in the 'each' expression and take another spin in the 2484 // Store the entry in the 'each' expression and take another spin in the
2481 // loop. r3: i'th entry of the enum cache (or string there of) 2485 // loop. r3: i'th entry of the enum cache (or string there of)
2482 frame_->EmitPush(r3); // push entry 2486 frame_->EmitPush(r3); // push entry
2483 { Reference each(this, node->each()); 2487 { Reference each(this, node->each());
2484 if (!each.is_illegal()) { 2488 if (!each.is_illegal()) {
2485 if (each.size() > 0) { 2489 if (each.size() > 0) {
2486 __ ldr(r0, frame_->ElementAt(each.size())); 2490 __ ldr(r0, frame_->ElementAt(each.size()));
2487 frame_->EmitPush(r0); 2491 frame_->EmitPush(r0);
2488 each.SetValue(NOT_CONST_INIT); 2492 each.SetValue(NOT_CONST_INIT, UNLIKELY_SMI);
2489 frame_->Drop(2); 2493 frame_->Drop(2);
2490 } else { 2494 } else {
2491 // If the reference was to a slot we rely on the convenient property 2495 // If the reference was to a slot we rely on the convenient property
2492 // that it doesn't matter whether a value (eg, r3 pushed above) is 2496 // that it doesn't matter whether a value (eg, r3 pushed above) is
2493 // right on top of or right underneath a zero-sized reference. 2497 // right on top of or right underneath a zero-sized reference.
2494 each.SetValue(NOT_CONST_INIT); 2498 each.SetValue(NOT_CONST_INIT, UNLIKELY_SMI);
2495 frame_->Drop(); 2499 frame_->Drop();
2496 } 2500 }
2497 } 2501 }
2498 } 2502 }
2499 // Body. 2503 // Body.
2500 CheckStack(); // TODO(1222600): ignore if body contains calls. 2504 CheckStack(); // TODO(1222600): ignore if body contains calls.
2501 Visit(node->body()); 2505 Visit(node->body());
2502 2506
2503 // Next. Reestablish a spilled frame in case we are coming here via 2507 // Next. Reestablish a spilled frame in case we are coming here via
2504 // a continue in the body. 2508 // a continue in the body.
(...skipping 1134 matching lines...) Expand 10 before | Expand all | Expand 10 after
3639 #ifdef DEBUG 3643 #ifdef DEBUG
3640 int original_height = frame_->height(); 3644 int original_height = frame_->height();
3641 #endif 3645 #endif
3642 Comment cmnt(masm_, "[ Keyed Property Assignment"); 3646 Comment cmnt(masm_, "[ Keyed Property Assignment");
3643 Property* prop = node->target()->AsProperty(); 3647 Property* prop = node->target()->AsProperty();
3644 ASSERT_NOT_NULL(prop); 3648 ASSERT_NOT_NULL(prop);
3645 3649
3646 // Evaluate the receiver subexpression. 3650 // Evaluate the receiver subexpression.
3647 Load(prop->obj()); 3651 Load(prop->obj());
3648 3652
3653 WriteBarrierCharacter wb_info;
3654
3649 // Change to slow case in the beginning of an initialization block to 3655 // Change to slow case in the beginning of an initialization block to
3650 // avoid the quadratic behavior of repeatedly adding fast properties. 3656 // avoid the quadratic behavior of repeatedly adding fast properties.
3651 if (node->starts_initialization_block()) { 3657 if (node->starts_initialization_block()) {
3652 frame_->Dup(); 3658 frame_->Dup();
3653 frame_->CallRuntime(Runtime::kToSlowProperties, 1); 3659 frame_->CallRuntime(Runtime::kToSlowProperties, 1);
3654 } 3660 }
3655 3661
3656 // Change to fast case at the end of an initialization block. To prepare for 3662 // Change to fast case at the end of an initialization block. To prepare for
3657 // that add an extra copy of the receiver to the frame, so that it can be 3663 // that add an extra copy of the receiver to the frame, so that it can be
3658 // converted back to fast case after the assignment. 3664 // converted back to fast case after the assignment.
3659 if (node->ends_initialization_block()) { 3665 if (node->ends_initialization_block()) {
3660 frame_->Dup(); 3666 frame_->Dup();
3661 } 3667 }
3662 3668
3663 // Evaluate the key subexpression. 3669 // Evaluate the key subexpression.
3664 Load(prop->key()); 3670 Load(prop->key());
3665 3671
3666 // Stack layout: 3672 // Stack layout:
3667 // [tos] : key 3673 // [tos] : key
3668 // [tos+1] : receiver 3674 // [tos+1] : receiver
3669 // [tos+2] : receiver if at the end of an initialization block 3675 // [tos+2] : receiver if at the end of an initialization block
3670 3676 //
3671 // Evaluate the right-hand side. 3677 // Evaluate the right-hand side.
3672 if (node->is_compound()) { 3678 if (node->is_compound()) {
3673 // For a compound assignment the right-hand side is a binary operation 3679 // For a compound assignment the right-hand side is a binary operation
3674 // between the current property value and the actual right-hand side. 3680 // between the current property value and the actual right-hand side.
3675 // Duplicate receiver and key for loading the current property value. 3681 // Duplicate receiver and key for loading the current property value.
3676 frame_->Dup2(); 3682 frame_->Dup2();
3677 EmitKeyedLoad(); 3683 EmitKeyedLoad();
3678 frame_->EmitPush(r0); 3684 frame_->EmitPush(r0);
3679 3685
3680 // Perform the binary operation. 3686 // Perform the binary operation.
(...skipping 11 matching lines...) Expand all
3692 loop_nesting() > 0 ? GENERATE_INLINE_SMI : DONT_GENERATE_INLINE_SMI; 3698 loop_nesting() > 0 ? GENERATE_INLINE_SMI : DONT_GENERATE_INLINE_SMI;
3693 if (literal != NULL) { 3699 if (literal != NULL) {
3694 ASSERT(!literal->handle()->IsSmi()); 3700 ASSERT(!literal->handle()->IsSmi());
3695 inline_smi = DONT_GENERATE_INLINE_SMI; 3701 inline_smi = DONT_GENERATE_INLINE_SMI;
3696 } 3702 }
3697 Load(node->value()); 3703 Load(node->value());
3698 GenericBinaryOperation(node->binary_op(), 3704 GenericBinaryOperation(node->binary_op(),
3699 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE, 3705 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE,
3700 inline_smi); 3706 inline_smi);
3701 } 3707 }
3708 wb_info = node->type()->IsLikelySmi() ? LIKELY_SMI : UNLIKELY_SMI;
3702 } else { 3709 } else {
3703 // For non-compound assignment just load the right-hand side. 3710 // For non-compound assignment just load the right-hand side.
3704 Load(node->value()); 3711 Load(node->value());
3712 wb_info = node->value()->AsLiteral() != NULL ?
3713 NEVER_NEWSPACE :
3714 (node->value()->type()->IsLikelySmi() ? LIKELY_SMI : UNLIKELY_SMI);
3705 } 3715 }
3706 3716
3707 // Stack layout: 3717 // Stack layout:
3708 // [tos] : value 3718 // [tos] : value
3709 // [tos+1] : key 3719 // [tos+1] : key
3710 // [tos+2] : receiver 3720 // [tos+2] : receiver
3711 // [tos+3] : receiver if at the end of an initialization block 3721 // [tos+3] : receiver if at the end of an initialization block
3712 3722
3713 // Perform the assignment. It is safe to ignore constants here. 3723 // Perform the assignment. It is safe to ignore constants here.
3714 ASSERT(node->op() != Token::INIT_CONST); 3724 ASSERT(node->op() != Token::INIT_CONST);
3715 CodeForSourcePosition(node->position()); 3725 CodeForSourcePosition(node->position());
3716 EmitKeyedStore(prop->key()->type()); 3726 EmitKeyedStore(prop->key()->type(), wb_info);
3717 frame_->EmitPush(r0); 3727 frame_->EmitPush(r0);
3718 3728
3719 // Stack layout: 3729 // Stack layout:
3720 // [tos] : result 3730 // [tos] : result
3721 // [tos+1] : receiver if at the end of an initialization block 3731 // [tos+1] : receiver if at the end of an initialization block
3722 3732
3723 // Change to fast case at the end of an initialization block. 3733 // Change to fast case at the end of an initialization block.
3724 if (node->ends_initialization_block()) { 3734 if (node->ends_initialization_block()) {
3725 // The argument to the runtime call is the extra copy of the receiver, 3735 // The argument to the runtime call is the extra copy of the receiver,
3726 // which is below the value of the assignment. Swap the receiver and 3736 // which is below the value of the assignment. Swap the receiver and
(...skipping 1775 matching lines...) Expand 10 before | Expand all | Expand 10 after
5502 ASSERT(!target.is_illegal()); 5512 ASSERT(!target.is_illegal());
5503 target.GetValue(); // Pushes the value. 5513 target.GetValue(); // Pushes the value.
5504 Register value = frame_->PopToRegister(); 5514 Register value = frame_->PopToRegister();
5505 if (is_postfix) frame_->EmitPush(value); 5515 if (is_postfix) frame_->EmitPush(value);
5506 if (is_increment) { 5516 if (is_increment) {
5507 __ add(value, value, Operand(Smi::FromInt(1))); 5517 __ add(value, value, Operand(Smi::FromInt(1)));
5508 } else { 5518 } else {
5509 __ sub(value, value, Operand(Smi::FromInt(1))); 5519 __ sub(value, value, Operand(Smi::FromInt(1)));
5510 } 5520 }
5511 frame_->EmitPush(value); 5521 frame_->EmitPush(value);
5512 target.SetValue(NOT_CONST_INIT); 5522 target.SetValue(NOT_CONST_INIT, LIKELY_SMI);
5513 if (is_postfix) frame_->Pop(); 5523 if (is_postfix) frame_->Pop();
5514 ASSERT_EQ(original_height + 1, frame_->height()); 5524 ASSERT_EQ(original_height + 1, frame_->height());
5515 return; 5525 return;
5516 } 5526 }
5517 5527
5518 // If it's a postfix expression and its result is not ignored and the 5528 // If it's a postfix expression and its result is not ignored and the
5519 // reference is non-trivial, then push a placeholder on the stack now 5529 // reference is non-trivial, then push a placeholder on the stack now
5520 // to hold the result of the expression. 5530 // to hold the result of the expression.
5521 bool placeholder_pushed = false; 5531 bool placeholder_pushed = false;
5522 if (!is_slot && is_postfix) { 5532 if (!is_slot && is_postfix) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
5601 } 5611 }
5602 5612
5603 __ Move(value, r0); 5613 __ Move(value, r0);
5604 // Store the new value in the target if not const. 5614 // Store the new value in the target if not const.
5605 // At this point the answer is in the value register. 5615 // At this point the answer is in the value register.
5606 exit.Bind(); 5616 exit.Bind();
5607 frame_->EmitPush(value); 5617 frame_->EmitPush(value);
5608 // Set the target with the result, leaving the result on 5618 // Set the target with the result, leaving the result on
5609 // top of the stack. Removes the target from the stack if 5619 // top of the stack. Removes the target from the stack if
5610 // it has a non-zero size. 5620 // it has a non-zero size.
5611 if (!is_const) target.SetValue(NOT_CONST_INIT); 5621 if (!is_const) target.SetValue(NOT_CONST_INIT, LIKELY_SMI);
5612 } 5622 }
5613 5623
5614 // Postfix: Discard the new value and use the old. 5624 // Postfix: Discard the new value and use the old.
5615 if (is_postfix) frame_->Pop(); 5625 if (is_postfix) frame_->Pop();
5616 ASSERT_EQ(original_height + 1, frame_->height()); 5626 ASSERT_EQ(original_height + 1, frame_->height());
5617 } 5627 }
5618 5628
5619 5629
5620 void CodeGenerator::GenerateLogicalBooleanOperation(BinaryOperation* node) { 5630 void CodeGenerator::GenerateLogicalBooleanOperation(BinaryOperation* node) {
5621 // According to ECMA-262 section 11.11, page 58, the binary logical 5631 // According to ECMA-262 section 11.11, page 58, the binary logical
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after
6334 // Make sure that the expected number of instructions are generated. 6344 // Make sure that the expected number of instructions are generated.
6335 ASSERT_EQ(GetInlinedKeyedLoadInstructionsAfterPatch(), 6345 ASSERT_EQ(GetInlinedKeyedLoadInstructionsAfterPatch(),
6336 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); 6346 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
6337 } 6347 }
6338 6348
6339 deferred->BindExit(); 6349 deferred->BindExit();
6340 } 6350 }
6341 } 6351 }
6342 6352
6343 6353
6344 void CodeGenerator::EmitKeyedStore(StaticType* key_type) { 6354 void CodeGenerator::EmitKeyedStore(StaticType* key_type,
6355 WriteBarrierCharacter wb_info) {
6345 // Generate inlined version of the keyed store if the code is in a loop 6356 // Generate inlined version of the keyed store if the code is in a loop
6346 // and the key is likely to be a smi. 6357 // and the key is likely to be a smi.
6347 if (loop_nesting() > 0 && key_type->IsLikelySmi()) { 6358 if (loop_nesting() > 0 && key_type->IsLikelySmi()) {
6348 // Inline the keyed store. 6359 // Inline the keyed store.
6349 Comment cmnt(masm_, "[ Inlined store to keyed property"); 6360 Comment cmnt(masm_, "[ Inlined store to keyed property");
6350 6361
6351 Register scratch1 = VirtualFrame::scratch0(); 6362 Register scratch1 = VirtualFrame::scratch0();
6352 Register scratch2 = VirtualFrame::scratch1(); 6363 Register scratch2 = VirtualFrame::scratch1();
6353 Register scratch3 = r3; 6364 Register scratch3 = r3;
6354 6365
6355 // Counter will be decremented in the deferred code. Placed here to avoid 6366 // Counter will be decremented in the deferred code. Placed here to avoid
6356 // having it in the instruction stream below where patching will occur. 6367 // having it in the instruction stream below where patching will occur.
6357 __ IncrementCounter(&Counters::keyed_store_inline, 1, 6368 __ IncrementCounter(&Counters::keyed_store_inline, 1,
6358 scratch1, scratch2); 6369 scratch1, scratch2);
6359 6370
6371
6372
6360 // Load the value, key and receiver from the stack. 6373 // Load the value, key and receiver from the stack.
6374 bool value_is_harmless = frame_->KnownSmiAt(0);
6375 if (wb_info == NEVER_NEWSPACE) value_is_harmless = true;
6376 bool key_is_smi = frame_->KnownSmiAt(1);
6361 Register value = frame_->PopToRegister(); 6377 Register value = frame_->PopToRegister();
6362 Register key = frame_->PopToRegister(value); 6378 Register key = frame_->PopToRegister(value);
6363 VirtualFrame::SpilledScope spilled(frame_); 6379 VirtualFrame::SpilledScope spilled(frame_);
6364 Register receiver = r2; 6380 Register receiver = r2;
6365 frame_->EmitPop(receiver); 6381 frame_->EmitPop(receiver);
6366 6382
6383 #ifdef DEBUG
6384 bool we_remembered_the_write_barrier = value_is_harmless;
6385 #endif
6386
6367 // The deferred code expects value, key and receiver in registers. 6387 // The deferred code expects value, key and receiver in registers.
6368 DeferredReferenceSetKeyedValue* deferred = 6388 DeferredReferenceSetKeyedValue* deferred =
6369 new DeferredReferenceSetKeyedValue(value, key, receiver); 6389 new DeferredReferenceSetKeyedValue(value, key, receiver);
6370 6390
6371 // Check that the value is a smi. As this inlined code does not set the 6391 // Check that the value is a smi. As this inlined code does not set the
6372 // write barrier it is only possible to store smi values. 6392 // write barrier it is only possible to store smi values.
6373 __ tst(value, Operand(kSmiTagMask)); 6393 if (!value_is_harmless) {
6374 deferred->Branch(ne); 6394 // If the value is not likely to be a Smi then lets test the fixed array
William Hesse 2010/07/01 15:00:59 let's
6395 // for new space instead. See below.
6396 if (wb_info == LIKELY_SMI) {
6397 __ tst(value, Operand(kSmiTagMask));
6398 deferred->Branch(ne);
6399 #ifdef DEBUG
6400 we_remembered_the_write_barrier = true;
6401 #endif
6402 }
6403 }
6375 6404
6376 // Check that the key is a smi. 6405 if (!key_is_smi) {
6377 __ tst(key, Operand(kSmiTagMask)); 6406 // Check that the key is a smi.
6378 deferred->Branch(ne); 6407 __ tst(key, Operand(kSmiTagMask));
6408 deferred->Branch(ne);
6409 }
6379 6410
6380 // Check that the receiver is a heap object. 6411 // Check that the receiver is a heap object.
6381 __ tst(receiver, Operand(kSmiTagMask)); 6412 __ tst(receiver, Operand(kSmiTagMask));
6382 deferred->Branch(eq); 6413 deferred->Branch(eq);
6383 6414
6384 // Check that the receiver is a JSArray. 6415 // Check that the receiver is a JSArray.
6385 __ CompareObjectType(receiver, scratch1, scratch1, JS_ARRAY_TYPE); 6416 __ CompareObjectType(receiver, scratch1, scratch1, JS_ARRAY_TYPE);
6386 deferred->Branch(ne); 6417 deferred->Branch(ne);
6387 6418
6388 // Check that the key is within bounds. Both the key and the length of 6419 // Check that the key is within bounds. Both the key and the length of
6389 // the JSArray are smis. Use unsigned comparison to handle negative keys. 6420 // the JSArray are smis. Use unsigned comparison to handle negative keys.
6390 __ ldr(scratch1, FieldMemOperand(receiver, JSArray::kLengthOffset)); 6421 __ ldr(scratch1, FieldMemOperand(receiver, JSArray::kLengthOffset));
6391 __ cmp(scratch1, key); 6422 __ cmp(scratch1, key);
6392 deferred->Branch(ls); // Unsigned less equal. 6423 deferred->Branch(ls); // Unsigned less equal.
6393 6424
6425 // Get the elements array from the receiver and check that it
6426 // is not a dictionary.
William Hesse 2010/07/01 15:00:59 The check that it is a dictionary is pretty far aw
6427 __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset));
6428 if (!value_is_harmless && wb_info != LIKELY_SMI) {
6429 Label ok;
6430 __ and_(scratch2, scratch1, Operand(ExternalReference::new_space_mask()));
6431 __ cmp(scratch2, Operand(ExternalReference::new_space_start()));
6432 __ tst(value, Operand(kSmiTagMask), ne);
6433 deferred->Branch(ne);
6434 #ifdef DEBUG
6435 we_remembered_the_write_barrier = true;
6436 #endif
6437 }
6438 __ ldr(scratch2, FieldMemOperand(scratch1, JSObject::kMapOffset));
6394 // The following instructions are the part of the inlined store keyed 6439 // The following instructions are the part of the inlined store keyed
6395 // property code which can be patched. Therefore the exact number of 6440 // property code which can be patched. Therefore the exact number of
6396 // instructions generated need to be fixed, so the constant pool is blocked 6441 // instructions generated need to be fixed, so the constant pool is blocked
6397 // while generating this code. 6442 // while generating this code.
6398 { Assembler::BlockConstPoolScope block_const_pool(masm_); 6443 { Assembler::BlockConstPoolScope block_const_pool(masm_);
6399 // Get the elements array from the receiver and check that it 6444 #ifdef DEBUG
6400 // is not a dictionary. 6445 Label check_inlined_codesize;
6401 __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset)); 6446 masm_->bind(&check_inlined_codesize);
6402 __ ldr(scratch2, FieldMemOperand(scratch1, JSObject::kMapOffset)); 6447 #endif
6448
6403 // Read the fixed array map from the constant pool (not from the root 6449 // Read the fixed array map from the constant pool (not from the root
6404 // array) so that the value can be patched. When debugging, we patch this 6450 // array) so that the value can be patched. When debugging, we patch this
6405 // comparison to always fail so that we will hit the IC call in the 6451 // comparison to always fail so that we will hit the IC call in the
6406 // deferred code which will allow the debugger to break for fast case 6452 // deferred code which will allow the debugger to break for fast case
6407 // stores. 6453 // stores.
6408 #ifdef DEBUG
6409 Label check_inlined_codesize;
6410 masm_->bind(&check_inlined_codesize);
6411 #endif
6412 __ mov(scratch3, Operand(Factory::fixed_array_map())); 6454 __ mov(scratch3, Operand(Factory::fixed_array_map()));
6413 __ cmp(scratch2, scratch3); 6455 __ cmp(scratch2, scratch3);
6414 deferred->Branch(ne); 6456 deferred->Branch(ne);
6415 6457
6416 // Store the value. 6458 // Store the value.
6417 __ add(scratch1, scratch1, 6459 __ add(scratch1, scratch1,
6418 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 6460 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
6419 __ str(value, 6461 __ str(value,
6420 MemOperand(scratch1, key, LSL, 6462 MemOperand(scratch1, key, LSL,
6421 kPointerSizeLog2 - (kSmiTagSize + kSmiShiftSize))); 6463 kPointerSizeLog2 - (kSmiTagSize + kSmiShiftSize)));
6422 6464
6423 // Make sure that the expected number of instructions are generated. 6465 // Make sure that the expected number of instructions are generated.
6424 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch, 6466 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch,
6425 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); 6467 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
6426 } 6468 }
6427 6469
6470 ASSERT(we_remembered_the_write_barrier);
6471
6428 deferred->BindExit(); 6472 deferred->BindExit();
6429 } else { 6473 } else {
6430 frame()->CallKeyedStoreIC(); 6474 frame()->CallKeyedStoreIC();
6431 } 6475 }
6432 } 6476 }
6433 6477
6434 6478
6435 #ifdef DEBUG 6479 #ifdef DEBUG
6436 bool CodeGenerator::HasValidEntryRegisters() { return true; } 6480 bool CodeGenerator::HasValidEntryRegisters() { return true; }
6437 #endif 6481 #endif
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
6515 cgen_->frame()->EmitPush(r0); 6559 cgen_->frame()->EmitPush(r0);
6516 break; 6560 break;
6517 } 6561 }
6518 6562
6519 default: 6563 default:
6520 UNREACHABLE(); 6564 UNREACHABLE();
6521 } 6565 }
6522 } 6566 }
6523 6567
6524 6568
6525 void Reference::SetValue(InitState init_state) { 6569 void Reference::SetValue(InitState init_state, WriteBarrierCharacter wb_info) {
6526 ASSERT(!is_illegal()); 6570 ASSERT(!is_illegal());
6527 ASSERT(!cgen_->has_cc()); 6571 ASSERT(!cgen_->has_cc());
6528 MacroAssembler* masm = cgen_->masm(); 6572 MacroAssembler* masm = cgen_->masm();
6529 VirtualFrame* frame = cgen_->frame(); 6573 VirtualFrame* frame = cgen_->frame();
6530 Property* property = expression_->AsProperty(); 6574 Property* property = expression_->AsProperty();
6531 if (property != NULL) { 6575 if (property != NULL) {
6532 cgen_->CodeForSourcePosition(property->position()); 6576 cgen_->CodeForSourcePosition(property->position());
6533 } 6577 }
6534 6578
6535 switch (type_) { 6579 switch (type_) {
(...skipping 11 matching lines...) Expand all
6547 frame->EmitPush(r0); 6591 frame->EmitPush(r0);
6548 set_unloaded(); 6592 set_unloaded();
6549 break; 6593 break;
6550 } 6594 }
6551 6595
6552 case KEYED: { 6596 case KEYED: {
6553 Comment cmnt(masm, "[ Store to keyed Property"); 6597 Comment cmnt(masm, "[ Store to keyed Property");
6554 Property* property = expression_->AsProperty(); 6598 Property* property = expression_->AsProperty();
6555 ASSERT(property != NULL); 6599 ASSERT(property != NULL);
6556 cgen_->CodeForSourcePosition(property->position()); 6600 cgen_->CodeForSourcePosition(property->position());
6557 cgen_->EmitKeyedStore(property->key()->type()); 6601 cgen_->EmitKeyedStore(property->key()->type(), wb_info);
6558 frame->EmitPush(r0); 6602 frame->EmitPush(r0);
6559 set_unloaded(); 6603 set_unloaded();
6560 break; 6604 break;
6561 } 6605 }
6562 6606
6563 default: 6607 default:
6564 UNREACHABLE(); 6608 UNREACHABLE();
6565 } 6609 }
6566 } 6610 }
6567 6611
(...skipping 4554 matching lines...) Expand 10 before | Expand all | Expand 10 after
11122 __ bind(&string_add_runtime); 11166 __ bind(&string_add_runtime);
11123 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 11167 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
11124 } 11168 }
11125 11169
11126 11170
11127 #undef __ 11171 #undef __
11128 11172
11129 } } // namespace v8::internal 11173 } } // namespace v8::internal
11130 11174
11131 #endif // V8_TARGET_ARCH_ARM 11175 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698