OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |