| Index: src/arm/codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/codegen-arm.cc (revision 4568)
|
| +++ src/arm/codegen-arm.cc (working copy)
|
| @@ -565,7 +565,7 @@
|
| }
|
| ASSERT(has_valid_frame());
|
| ASSERT(!has_cc());
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -2717,7 +2717,7 @@
|
| return;
|
| }
|
| InstantiateFunction(function_info);
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -2729,7 +2729,7 @@
|
| VirtualFrame::SpilledScope spilled_scope(frame_);
|
| Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
|
| InstantiateFunction(node->shared_function_info());
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -2756,7 +2756,7 @@
|
| LoadAndSpill(node->else_expression());
|
| if (exit.is_linked()) exit.Bind();
|
| }
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -3028,7 +3028,7 @@
|
| #endif
|
| Comment cmnt(masm_, "[ Slot");
|
| LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF);
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -3047,7 +3047,7 @@
|
| Reference ref(this, node);
|
| ref.GetValue();
|
| }
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -3059,7 +3059,7 @@
|
| Register reg = frame_->GetTOSRegister();
|
| __ mov(reg, Operand(node->handle()));
|
| frame_->EmitPush(reg);
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -3103,7 +3103,7 @@
|
| done.Bind();
|
| // Push the literal.
|
| frame_->EmitPush(r2);
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -3184,7 +3184,7 @@
|
| }
|
| }
|
| }
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -3243,7 +3243,7 @@
|
| __ mov(r3, Operand(offset));
|
| __ RecordWrite(r1, r3, r2);
|
| }
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -3259,73 +3259,321 @@
|
| LoadAndSpill(node->value());
|
| frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
|
| frame_->EmitPush(r0);
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| -void CodeGenerator::VisitAssignment(Assignment* node) {
|
| - VirtualFrame::RegisterAllocationScope scope(this);
|
| +void CodeGenerator::EmitSlotAssignment(Assignment* node) {
|
| #ifdef DEBUG
|
| int original_height = frame_->height();
|
| #endif
|
| - Comment cmnt(masm_, "[ Assignment");
|
| + Comment cmnt(masm(), "[ Variable Assignment");
|
| + Variable* var = node->target()->AsVariableProxy()->AsVariable();
|
| + ASSERT(var != NULL);
|
| + Slot* slot = var->slot();
|
| + ASSERT(slot != NULL);
|
|
|
| - { Reference target(this, node->target(), node->is_compound());
|
| - if (target.is_illegal()) {
|
| - // Fool the virtual frame into thinking that we left the assignment's
|
| - // value on the frame.
|
| - Register tos = frame_->GetTOSRegister();
|
| - __ mov(tos, Operand(Smi::FromInt(0)));
|
| - frame_->EmitPush(tos);
|
| - ASSERT(frame_->height() == original_height + 1);
|
| - return;
|
| + // Evaluate the right-hand side.
|
| + if (node->is_compound()) {
|
| + // For a compound assignment the right-hand side is a binary operation
|
| + // between the current property value and the actual right-hand side.
|
| + LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
|
| +
|
| + // Perform the binary operation.
|
| + Literal* literal = node->value()->AsLiteral();
|
| + bool overwrite_value =
|
| + (node->value()->AsBinaryOperation() != NULL &&
|
| + node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
|
| + if (literal != NULL && literal->handle()->IsSmi()) {
|
| + SmiOperation(node->binary_op(),
|
| + literal->handle(),
|
| + false,
|
| + overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
|
| + } else {
|
| + Load(node->value());
|
| + VirtualFrameBinaryOperation(
|
| + node->binary_op(), overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
|
| }
|
| + } else {
|
| + Load(node->value());
|
| + }
|
|
|
| - if (node->op() == Token::ASSIGN ||
|
| - node->op() == Token::INIT_VAR ||
|
| - node->op() == Token::INIT_CONST) {
|
| + // Perform the assignment.
|
| + if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) {
|
| + CodeForSourcePosition(node->position());
|
| + StoreToSlot(slot,
|
| + node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT);
|
| + }
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| +}
|
| +
|
| +
|
| +void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
|
| +#ifdef DEBUG
|
| + int original_height = frame_->height();
|
| +#endif
|
| + Comment cmnt(masm(), "[ Named Property Assignment");
|
| + Variable* var = node->target()->AsVariableProxy()->AsVariable();
|
| + Property* prop = node->target()->AsProperty();
|
| + ASSERT(var == NULL || (prop == NULL && var->is_global()));
|
| +
|
| + // Initialize name and evaluate the receiver sub-expression if necessary. If
|
| + // the receiver is trivial it is not placed on the stack at this point, but
|
| + // loaded whenever actually needed.
|
| + Handle<String> name;
|
| + bool is_trivial_receiver = false;
|
| + if (var != NULL) {
|
| + name = var->name();
|
| + } else {
|
| + Literal* lit = prop->key()->AsLiteral();
|
| + ASSERT_NOT_NULL(lit);
|
| + name = Handle<String>::cast(lit->handle());
|
| + // Do not materialize the receiver on the frame if it is trivial.
|
| + is_trivial_receiver = prop->obj()->IsTrivial();
|
| + if (!is_trivial_receiver) Load(prop->obj());
|
| + }
|
| +
|
| + // Change to slow case in the beginning of an initialization block to
|
| + // avoid the quadratic behavior of repeatedly adding fast properties.
|
| + if (node->starts_initialization_block()) {
|
| + // Initialization block consists of assignments on the form expr.x = ..., so
|
| + // this will never be an assignment to a variable, so there must be a
|
| + // receiver object.
|
| + ASSERT_EQ(NULL, var);
|
| + if (is_trivial_receiver) {
|
| + Load(prop->obj());
|
| + } else {
|
| + frame_->Dup();
|
| + }
|
| + frame_->CallRuntime(Runtime::kToSlowProperties, 1);
|
| + }
|
| +
|
| + // Change to fast case at the end of an initialization block. To prepare for
|
| + // that add an extra copy of the receiver to the frame, so that it can be
|
| + // converted back to fast case after the assignment.
|
| + if (node->ends_initialization_block() && !is_trivial_receiver) {
|
| + frame_->Dup();
|
| + }
|
| +
|
| + // Stack layout:
|
| + // [tos] : receiver (only materialized if non-trivial)
|
| + // [tos+1] : receiver if at the end of an initialization block
|
| +
|
| + // Evaluate the right-hand side.
|
| + if (node->is_compound()) {
|
| + // For a compound assignment the right-hand side is a binary operation
|
| + // between the current property value and the actual right-hand side.
|
| + if (is_trivial_receiver) {
|
| + Load(prop->obj());
|
| + } else if (var != NULL) {
|
| + LoadGlobal();
|
| + } else {
|
| + frame_->Dup();
|
| + }
|
| + EmitNamedLoad(name, var != NULL);
|
| + frame_->Drop(); // Receiver is left on the stack.
|
| + frame_->EmitPush(r0);
|
| +
|
| + // Perform the binary operation.
|
| + Literal* literal = node->value()->AsLiteral();
|
| + bool overwrite_value =
|
| + (node->value()->AsBinaryOperation() != NULL &&
|
| + node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
|
| + if (literal != NULL && literal->handle()->IsSmi()) {
|
| + SmiOperation(node->binary_op(),
|
| + literal->handle(),
|
| + false,
|
| + overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
|
| + } else {
|
| Load(node->value());
|
| + VirtualFrameBinaryOperation(
|
| + node->binary_op(), overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
|
| + }
|
| + } else {
|
| + // For non-compound assignment just load the right-hand side.
|
| + Load(node->value());
|
| + }
|
|
|
| - } else { // Assignment is a compound assignment.
|
| - // Get the old value of the lhs.
|
| - target.GetValue();
|
| - Literal* literal = node->value()->AsLiteral();
|
| - bool overwrite =
|
| - (node->value()->AsBinaryOperation() != NULL &&
|
| - node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
|
| - if (literal != NULL && literal->handle()->IsSmi()) {
|
| - SmiOperation(node->binary_op(),
|
| - literal->handle(),
|
| - false,
|
| - overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE);
|
| - } else {
|
| - Load(node->value());
|
| - VirtualFrameBinaryOperation(node->binary_op(),
|
| - overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE);
|
| - }
|
| + // Stack layout:
|
| + // [tos] : value
|
| + // [tos+1] : receiver (only materialized if non-trivial)
|
| + // [tos+2] : receiver if at the end of an initialization block
|
| +
|
| + // Perform the assignment. It is safe to ignore constants here.
|
| + ASSERT(var == NULL || var->mode() != Variable::CONST);
|
| + ASSERT_NE(Token::INIT_CONST, node->op());
|
| + if (is_trivial_receiver) {
|
| + // Load the receiver and swap with the value.
|
| + Load(prop->obj());
|
| + Register t0 = frame_->PopToRegister();
|
| + Register t1 = frame_->PopToRegister(t0);
|
| + frame_->EmitPush(t0);
|
| + frame_->EmitPush(t1);
|
| + }
|
| + CodeForSourcePosition(node->position());
|
| + bool is_contextual = (var != NULL);
|
| + EmitNamedStore(name, is_contextual);
|
| + frame_->EmitPush(r0);
|
| +
|
| + // Change to fast case at the end of an initialization block.
|
| + if (node->ends_initialization_block()) {
|
| + ASSERT_EQ(NULL, var);
|
| + // The argument to the runtime call is the receiver.
|
| + if (is_trivial_receiver) {
|
| + Load(prop->obj());
|
| + } else {
|
| + // A copy of the receiver is below the value of the assignment. Swap
|
| + // the receiver and the value of the assignment expression.
|
| + Register t0 = frame_->PopToRegister();
|
| + Register t1 = frame_->PopToRegister(t0);
|
| + frame_->EmitPush(t0);
|
| + frame_->EmitPush(t1);
|
| }
|
| - Variable* var = node->target()->AsVariableProxy()->AsVariable();
|
| - if (var != NULL &&
|
| - (var->mode() == Variable::CONST) &&
|
| - node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
|
| - // Assignment ignored - leave the value on the stack.
|
| - UnloadReference(&target);
|
| + frame_->CallRuntime(Runtime::kToFastProperties, 1);
|
| + }
|
| +
|
| + // Stack layout:
|
| + // [tos] : result
|
| +
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| +}
|
| +
|
| +
|
| +void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
|
| +#ifdef DEBUG
|
| + int original_height = frame_->height();
|
| +#endif
|
| + Comment cmnt(masm_, "[ Keyed Property Assignment");
|
| + Property* prop = node->target()->AsProperty();
|
| + ASSERT_NOT_NULL(prop);
|
| +
|
| + // Evaluate the receiver subexpression.
|
| + Load(prop->obj());
|
| +
|
| + // Change to slow case in the beginning of an initialization block to
|
| + // avoid the quadratic behavior of repeatedly adding fast properties.
|
| + if (node->starts_initialization_block()) {
|
| + frame_->Dup();
|
| + frame_->CallRuntime(Runtime::kToSlowProperties, 1);
|
| + }
|
| +
|
| + // Change to fast case at the end of an initialization block. To prepare for
|
| + // that add an extra copy of the receiver to the frame, so that it can be
|
| + // converted back to fast case after the assignment.
|
| + if (node->ends_initialization_block()) {
|
| + frame_->Dup();
|
| + }
|
| +
|
| + // Evaluate the key subexpression.
|
| + Load(prop->key());
|
| +
|
| + // Stack layout:
|
| + // [tos] : key
|
| + // [tos+1] : receiver
|
| + // [tos+2] : receiver if at the end of an initialization block
|
| +
|
| + // Evaluate the right-hand side.
|
| + if (node->is_compound()) {
|
| + // For a compound assignment the right-hand side is a binary operation
|
| + // between the current property value and the actual right-hand side.
|
| + // Load of the current value leaves receiver and key on the stack.
|
| + EmitKeyedLoad();
|
| + frame_->EmitPush(r0);
|
| +
|
| + // Perform the binary operation.
|
| + Literal* literal = node->value()->AsLiteral();
|
| + bool overwrite_value =
|
| + (node->value()->AsBinaryOperation() != NULL &&
|
| + node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
|
| + if (literal != NULL && literal->handle()->IsSmi()) {
|
| + SmiOperation(node->binary_op(),
|
| + literal->handle(),
|
| + false,
|
| + overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
|
| } else {
|
| - CodeForSourcePosition(node->position());
|
| - if (node->op() == Token::INIT_CONST) {
|
| - // Dynamic constant initializations must use the function context
|
| - // and initialize the actual constant declared. Dynamic variable
|
| - // initializations are simply assignments and use SetValue.
|
| - target.SetValue(CONST_INIT);
|
| - } else {
|
| - target.SetValue(NOT_CONST_INIT);
|
| - }
|
| + Load(node->value());
|
| + VirtualFrameBinaryOperation(
|
| + node->binary_op(), overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
|
| }
|
| + } else {
|
| + // For non-compound assignment just load the right-hand side.
|
| + Load(node->value());
|
| }
|
| - ASSERT(frame_->height() == original_height + 1);
|
| +
|
| + // Stack layout:
|
| + // [tos] : value
|
| + // [tos+1] : key
|
| + // [tos+2] : receiver
|
| + // [tos+3] : receiver if at the end of an initialization block
|
| +
|
| + // Perform the assignment. It is safe to ignore constants here.
|
| + ASSERT(node->op() != Token::INIT_CONST);
|
| + CodeForSourcePosition(node->position());
|
| + frame_->PopToR0();
|
| + EmitKeyedStore(prop->key()->type());
|
| + frame_->Drop(2); // Key and receiver are left on the stack.
|
| + frame_->EmitPush(r0);
|
| +
|
| + // Stack layout:
|
| + // [tos] : result
|
| + // [tos+1] : receiver if at the end of an initialization block
|
| +
|
| + // Change to fast case at the end of an initialization block.
|
| + if (node->ends_initialization_block()) {
|
| + // The argument to the runtime call is the extra copy of the receiver,
|
| + // which is below the value of the assignment. Swap the receiver and
|
| + // the value of the assignment expression.
|
| + Register t0 = frame_->PopToRegister();
|
| + Register t1 = frame_->PopToRegister(t0);
|
| + frame_->EmitPush(t1);
|
| + frame_->EmitPush(t0);
|
| + frame_->CallRuntime(Runtime::kToFastProperties, 1);
|
| + }
|
| +
|
| + // Stack layout:
|
| + // [tos] : result
|
| +
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| +void CodeGenerator::VisitAssignment(Assignment* node) {
|
| + VirtualFrame::RegisterAllocationScope scope(this);
|
| +#ifdef DEBUG
|
| + int original_height = frame_->height();
|
| +#endif
|
| + Comment cmnt(masm_, "[ Assignment");
|
| +
|
| + Variable* var = node->target()->AsVariableProxy()->AsVariable();
|
| + Property* prop = node->target()->AsProperty();
|
| +
|
| + if (var != NULL && !var->is_global()) {
|
| + EmitSlotAssignment(node);
|
| +
|
| + } else if ((prop != NULL && prop->key()->IsPropertyName()) ||
|
| + (var != NULL && var->is_global())) {
|
| + // Properties whose keys are property names and global variables are
|
| + // treated as named property references. We do not need to consider
|
| + // global 'this' because it is not a valid left-hand side.
|
| + EmitNamedPropertyAssignment(node);
|
| +
|
| + } else if (prop != NULL) {
|
| + // Other properties (including rewritten parameters for a function that
|
| + // uses arguments) are keyed property assignments.
|
| + EmitKeyedPropertyAssignment(node);
|
| +
|
| + } else {
|
| + // Invalid left-hand side.
|
| + Load(node->target());
|
| + frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
|
| + // The runtime call doesn't actually return but the code generator will
|
| + // still generate code and expects a certain frame height.
|
| + frame_->EmitPush(r0);
|
| + }
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| +}
|
| +
|
| +
|
| void CodeGenerator::VisitThrow(Throw* node) {
|
| #ifdef DEBUG
|
| int original_height = frame_->height();
|
| @@ -3337,7 +3585,7 @@
|
| CodeForSourcePosition(node->position());
|
| frame_->CallRuntime(Runtime::kThrow, 1);
|
| frame_->EmitPush(r0);
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -3350,7 +3598,7 @@
|
| { Reference property(this, node);
|
| property.GetValue();
|
| }
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -3557,7 +3805,7 @@
|
| CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position());
|
| frame_->EmitPush(r0);
|
| }
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -3600,7 +3848,7 @@
|
|
|
| // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
|
| __ str(r0, frame_->Top());
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -4425,7 +4673,7 @@
|
| frame_->CallRuntime(function, arg_count);
|
| frame_->EmitPush(r0);
|
| }
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -4589,7 +4837,7 @@
|
| __ mov(r0, Operand(Smi::FromInt(0)));
|
| frame_->EmitPush(r0);
|
| }
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| return;
|
| }
|
| target.GetValue();
|
| @@ -4657,7 +4905,7 @@
|
|
|
| // Postfix: Discard the new value and use the old.
|
| if (is_postfix) frame_->EmitPop(r0);
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -4832,7 +5080,7 @@
|
| VirtualFrame::SpilledScope spilled_scope(frame_);
|
| __ ldr(r0, frame_->Function());
|
| frame_->EmitPush(r0);
|
| - ASSERT(frame_->height() == original_height + 1);
|
| + ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
|
|
| @@ -5226,6 +5474,16 @@
|
| }
|
|
|
|
|
| +void CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
|
| +#ifdef DEBUG
|
| + int expected_height = frame_->height() - (is_contextual ? 1 : 2);
|
| +#endif
|
| + frame_->CallStoreIC(name, is_contextual);
|
| +
|
| + ASSERT_EQ(expected_height, frame_->height());
|
| +}
|
| +
|
| +
|
| void CodeGenerator::EmitKeyedLoad() {
|
| if (loop_nesting() == 0) {
|
| VirtualFrame::SpilledScope spilled(frame_);
|
| @@ -5240,7 +5498,7 @@
|
| __ IncrementCounter(&Counters::keyed_load_inline, 1,
|
| frame_->scratch0(), frame_->scratch1());
|
|
|
| - // Load the receiver and key from the stack.
|
| + // Load the receiver and key from the stack.
|
| frame_->SpillAllButCopyTOSToR1R0();
|
| Register receiver = r0;
|
| Register key = r1;
|
| @@ -5315,7 +5573,7 @@
|
|
|
|
|
| void CodeGenerator::EmitKeyedStore(StaticType* key_type) {
|
| - frame_->AssertIsSpilled();
|
| + VirtualFrame::SpilledScope scope(frame_);
|
| // Generate inlined version of the keyed store if the code is in a loop
|
| // and the key is likely to be a smi.
|
| if (loop_nesting() > 0 && key_type->IsLikelySmi()) {
|
| @@ -5483,21 +5741,13 @@
|
| Comment cmnt(masm, "[ Store to Slot");
|
| Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
|
| cgen_->StoreToSlot(slot, init_state);
|
| - cgen_->UnloadReference(this);
|
| + set_unloaded();
|
| break;
|
| }
|
|
|
| case NAMED: {
|
| - VirtualFrame::SpilledScope scope(frame);
|
| Comment cmnt(masm, "[ Store to named Property");
|
| - // Call the appropriate IC code.
|
| - Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
| - Handle<String> name(GetName());
|
| -
|
| - frame->EmitPop(r0);
|
| - frame->EmitPop(r1);
|
| - __ mov(r2, Operand(name));
|
| - frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
|
| + cgen_->EmitNamedStore(GetName(), false);
|
| frame->EmitPush(r0);
|
| set_unloaded();
|
| break;
|
|
|