Chromium Code Reviews| Index: src/codegen-arm.cc |
| =================================================================== |
| --- src/codegen-arm.cc (revision 461) |
| +++ src/codegen-arm.cc (working copy) |
| @@ -51,6 +51,7 @@ |
| // on the execution stack to represent the reference. |
| enum InitState { CONST_INIT, NOT_CONST_INIT }; |
| +enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; |
| class Reference BASE_EMBEDDED { |
| public: |
| @@ -72,6 +73,18 @@ |
| bool is_slot() const { return type_ == SLOT; } |
| bool is_property() const { return type_ == NAMED || type_ == KEYED; } |
| + // Return the name. Only valid for named property references. |
| + Handle<String> GetName(); |
| + |
| + // Generate code to push the value of the reference on top of the |
| + // expression stack. The reference is expected to be already on top of |
| + // the expression stack, and it is left in place with its value above it. |
| + void GetValue(TypeofState typeof_state); |
| + |
| + // Generate code to store the value on top of the expression stack in the |
| + // reference. The reference is expected to be immediately below the value |
| + // on the expression stack. The stored value is left in place (with the |
| + // reference intact below it) to support chained assignments. |
| void SetValue(InitState init_state); |
| private: |
| @@ -91,42 +104,29 @@ |
| class CodeGenState BASE_EMBEDDED { |
| public: |
| - enum AccessType { |
| - UNDEFINED, |
| - LOAD, |
| - LOAD_TYPEOF_EXPR |
| - }; |
| - |
| // Create an initial code generator state. Destroying the initial state |
| // leaves the code generator with a NULL state. |
| explicit CodeGenState(ArmCodeGenerator* owner); |
| // Create a code generator state based on a code generator's current |
| - // state. The new state has its own access type and pair of branch |
| - // labels, and no reference. |
| + // state. The new state has its own typeof state and pair of branch |
| + // labels. |
| CodeGenState(ArmCodeGenerator* owner, |
| - AccessType access, |
| + TypeofState typeof_state, |
| Label* true_target, |
| Label* false_target); |
| - // Create a code generator state based on a code generator's current |
| - // state. The new state has an access type of LOAD, its own reference, |
| - // and inherits the pair of branch labels of the current state. |
| - CodeGenState(ArmCodeGenerator* owner, Reference* ref); |
| - |
| // Destroy a code generator state and restore the owning code generator's |
| // previous state. |
| ~CodeGenState(); |
| - AccessType access() const { return access_; } |
| - Reference* ref() const { return ref_; } |
| + TypeofState typeof_state() const { return typeof_state_; } |
| Label* true_target() const { return true_target_; } |
| Label* false_target() const { return false_target_; } |
| private: |
| ArmCodeGenerator* owner_; |
| - AccessType access_; |
| - Reference* ref_; |
| + TypeofState typeof_state_; |
| Label* true_target_; |
| Label* false_target_; |
| CodeGenState* previous_; |
| @@ -178,9 +178,7 @@ |
| // State |
| bool has_cc() const { return cc_reg_ != al; } |
| - CodeGenState::AccessType access() const { return state_->access(); } |
| - Reference* ref() const { return state_->ref(); } |
| - bool is_referenced() const { return state_->ref() != NULL; } |
| + TypeofState typeof_state() const { return state_->typeof_state(); } |
| Label* true_target() const { return state_->true_target(); } |
| Label* false_target() const { return state_->false_target(); } |
| @@ -209,12 +207,17 @@ |
| MemOperand SlotOperand(Slot* slot, Register tmp); |
| - void LoadCondition(Expression* x, CodeGenState::AccessType access, |
| - Label* true_target, Label* false_target, bool force_cc); |
| - void Load(Expression* x, |
| - CodeGenState::AccessType access = CodeGenState::LOAD); |
| + void LoadCondition(Expression* x, |
| + TypeofState typeof_state, |
| + Label* true_target, |
| + Label* false_target, |
| + bool force_cc); |
| + void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF); |
| void LoadGlobal(); |
| + // Read a value from a slot and leave it on top of the expression stack. |
| + void LoadFromSlot(Slot* slot, TypeofState typeof_state); |
| + |
| // Special code for typeof expressions: Unfortunately, we must |
| // be careful when loading the expression in 'typeof' |
| // expressions. We are not allowed to throw reference errors for |
| @@ -223,24 +226,6 @@ |
| // through the context chain. |
| void LoadTypeofExpression(Expression* x); |
| - |
| - // References |
| - |
| - // Generate code to fetch the value of a reference. The reference is |
| - // expected to be on top of the expression stack. It is left in place and |
| - // its value is pushed on top of it. |
| - void GetValue(Reference* ref) { |
| - ASSERT(!has_cc()); |
| - ASSERT(!ref->is_illegal()); |
| - CodeGenState new_state(this, ref); |
| - Visit(ref->expression()); |
| - } |
| - |
| - // Generate code to fetch a value from a property of a reference. The |
| - // reference is expected on top of the expression stack. It is left in |
| - // place and its value is pushed on top of it. |
| - void GetReferenceProperty(Expression* key); |
| - |
| void ToBoolean(Label* true_target, Label* false_target); |
| void GenericBinaryOperation(Token::Value op); |
| @@ -309,8 +294,7 @@ |
| CodeGenState::CodeGenState(ArmCodeGenerator* owner) |
| : owner_(owner), |
| - access_(UNDEFINED), |
| - ref_(NULL), |
| + typeof_state_(NOT_INSIDE_TYPEOF), |
| true_target_(NULL), |
| false_target_(NULL), |
| previous_(NULL) { |
| @@ -319,12 +303,11 @@ |
| CodeGenState::CodeGenState(ArmCodeGenerator* owner, |
| - AccessType access, |
| + TypeofState typeof_state, |
| Label* true_target, |
| Label* false_target) |
| : owner_(owner), |
| - access_(access), |
| - ref_(NULL), |
| + typeof_state_(typeof_state), |
| true_target_(true_target), |
| false_target_(false_target), |
| previous_(owner->state()) { |
| @@ -332,17 +315,6 @@ |
| } |
| -CodeGenState::CodeGenState(ArmCodeGenerator* owner, Reference* ref) |
| - : owner_(owner), |
| - access_(LOAD), |
| - ref_(ref), |
| - true_target_(owner->state()->true_target_), |
| - false_target_(owner->state()->false_target_), |
| - previous_(owner->state()) { |
| - owner_->set_state(this); |
| -} |
| - |
| - |
| CodeGenState::~CodeGenState() { |
| ASSERT(owner_->state() == this); |
| owner_->set_state(previous_); |
| @@ -708,15 +680,13 @@ |
| // code register and no value is pushed. If the condition code register was set, |
| // has_cc() is true and cc_reg_ contains the condition to test for 'true'. |
| void ArmCodeGenerator::LoadCondition(Expression* x, |
| - CodeGenState::AccessType access, |
| + TypeofState typeof_state, |
| Label* true_target, |
| Label* false_target, |
| bool force_cc) { |
| - ASSERT(access == CodeGenState::LOAD || |
| - access == CodeGenState::LOAD_TYPEOF_EXPR); |
| - ASSERT(!has_cc() && !is_referenced()); |
| + ASSERT(!has_cc()); |
| - { CodeGenState new_state(this, access, true_target, false_target); |
| + { CodeGenState new_state(this, typeof_state, true_target, false_target); |
| Visit(x); |
| } |
| if (force_cc && !has_cc()) { |
| @@ -727,13 +697,10 @@ |
| } |
| -void ArmCodeGenerator::Load(Expression* x, CodeGenState::AccessType access) { |
| - ASSERT(access == CodeGenState::LOAD || |
| - access == CodeGenState::LOAD_TYPEOF_EXPR); |
| - |
| +void ArmCodeGenerator::Load(Expression* x, TypeofState typeof_state) { |
| Label true_target; |
| Label false_target; |
| - LoadCondition(x, access, &true_target, &false_target, false); |
| + LoadCondition(x, typeof_state, &true_target, &false_target, false); |
| if (has_cc()) { |
| // convert cc_reg_ into a bool |
| @@ -786,8 +753,8 @@ |
| // TODO(1241834): Get rid of this function in favor of just using Load, now |
| -// that we have the LOAD_TYPEOF_EXPR access type. => Need to handle |
| -// global variables w/o reference errors elsewhere. |
| +// that we have the INSIDE_TYPEOF typeof state. => Need to handle global |
| +// variables w/o reference errors elsewhere. |
| void ArmCodeGenerator::LoadTypeofExpression(Expression* x) { |
| Variable* variable = x->AsVariableProxy()->AsVariable(); |
| if (variable != NULL && !variable->is_this() && variable->is_global()) { |
| @@ -801,7 +768,7 @@ |
| Property property(&global, &key, RelocInfo::kNoPosition); |
| Load(&property); |
| } else { |
| - Load(x, CodeGenState::LOAD_TYPEOF_EXPR); |
| + Load(x, INSIDE_TYPEOF); |
| } |
| } |
| @@ -818,6 +785,7 @@ |
| void ArmCodeGenerator::LoadReference(Reference* ref) { |
| + Comment cmnt(masm_, "[ LoadReference"); |
| Expression* e = ref->expression(); |
| Property* property = e->AsProperty(); |
| Variable* var = e->AsVariableProxy()->AsVariable(); |
| @@ -859,6 +827,7 @@ |
| void ArmCodeGenerator::UnloadReference(Reference* ref) { |
| + Comment cmnt(masm_, "[ UnloadReference"); |
| int size = ref->size(); |
| if (size <= 0) { |
| // Do nothing. No popping is necessary. |
| @@ -994,43 +963,6 @@ |
| }; |
| -void ArmCodeGenerator::GetReferenceProperty(Expression* key) { |
| - ASSERT(!ref()->is_illegal()); |
| - |
| - // TODO(1241834): Make sure that this it is safe to ignore the distinction |
| - // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance |
| - // that reference errors can be thrown below, we must distinguish between |
| - // the two kinds of loads (typeof expression loads must not throw a |
| - // reference error). |
| - if (ref()->type() == Reference::NAMED) { |
| - // Compute the name of the property. |
| - Literal* literal = key->AsLiteral(); |
| - Handle<String> name(String::cast(*literal->handle())); |
| - |
| - // Call the appropriate IC code. |
| - // Setup the name register. |
| - __ mov(r2, Operand(name)); |
| - Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| - Variable* var = ref()->expression()->AsVariableProxy()->AsVariable(); |
| - if (var != NULL) { |
| - ASSERT(var->is_global()); |
| - __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| - } else { |
| - __ Call(ic, RelocInfo::CODE_TARGET); |
| - } |
| - |
| - } else { |
| - // Access keyed property. |
| - ASSERT(ref()->type() == Reference::KEYED); |
| - |
| - // TODO(1224671): Implement inline caching for keyed loads as on ia32. |
| - GetPropertyStub stub; |
| - __ CallStub(&stub); |
| - } |
| - __ push(r0); |
| -} |
| - |
| - |
| void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) { |
| // sp[0] : y |
| // sp[1] : x |
| @@ -1527,7 +1459,7 @@ |
| Label then; |
| Label else_; |
| // if (cond) |
| - LoadCondition(node->condition(), CodeGenState::LOAD, &then, &else_, true); |
| + LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); |
| Branch(false, &else_); |
| // then |
| __ bind(&then); |
| @@ -1542,7 +1474,7 @@ |
| ASSERT(!has_else_stm); |
| Label then; |
| // if (cond) |
| - LoadCondition(node->condition(), CodeGenState::LOAD, &then, &exit, true); |
| + LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &exit, true); |
| Branch(false, &exit); |
| // then |
| __ bind(&then); |
| @@ -1553,7 +1485,7 @@ |
| ASSERT(!has_then_stm); |
| Label else_; |
| // if (!cond) |
| - LoadCondition(node->condition(), CodeGenState::LOAD, &exit, &else_, true); |
| + LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &else_, true); |
| Branch(true, &exit); |
| // else |
| __ bind(&else_); |
| @@ -1563,7 +1495,7 @@ |
| Comment cmnt(masm_, "[ If"); |
| ASSERT(!has_then_stm && !has_else_stm); |
| // if (cond) |
| - LoadCondition(node->condition(), CodeGenState::LOAD, &exit, &exit, false); |
| + LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false); |
| if (has_cc()) { |
| cc_reg_ = al; |
| } else { |
| @@ -1806,7 +1738,7 @@ |
| case DONT_KNOW: |
| CheckStack(); // TODO(1222600): ignore if body contains calls. |
| LoadCondition(node->cond(), |
| - CodeGenState::LOAD, |
| + NOT_INSIDE_TYPEOF, |
| &loop, |
| node->break_target(), |
| true); |
| @@ -1972,7 +1904,6 @@ |
| { Reference each(this, node->each()); |
| if (!each.is_illegal()) { |
| if (each.size() > 0) { |
| - // Reference's size is positive. |
| __ ldr(r0, MemOperand(sp, kPointerSize * each.size())); |
| __ push(r0); |
| } |
| @@ -2273,46 +2204,42 @@ |
| void ArmCodeGenerator::VisitConditional(Conditional* node) { |
| Comment cmnt(masm_, "[ Conditional"); |
| Label then, else_, exit; |
| - LoadCondition(node->condition(), CodeGenState::LOAD, &then, &else_, true); |
| + LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); |
| Branch(false, &else_); |
| __ bind(&then); |
| - Load(node->then_expression(), access()); |
| + Load(node->then_expression(), typeof_state()); |
| __ b(&exit); |
| __ bind(&else_); |
| - Load(node->else_expression(), access()); |
| + Load(node->else_expression(), typeof_state()); |
| __ bind(&exit); |
| } |
| -void ArmCodeGenerator::VisitSlot(Slot* node) { |
| - ASSERT(access() != CodeGenState::UNDEFINED); |
| - Comment cmnt(masm_, "[ Slot"); |
| +void ArmCodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { |
| + if (slot->type() == Slot::LOOKUP) { |
| + ASSERT(slot->var()->mode() == Variable::DYNAMIC); |
| - if (node->type() == Slot::LOOKUP) { |
| - ASSERT(node->var()->mode() == Variable::DYNAMIC); |
| - |
| // For now, just do a runtime call. |
| __ push(cp); |
| - __ mov(r0, Operand(node->var()->name())); |
| + __ mov(r0, Operand(slot->var()->name())); |
| __ push(r0); |
| - if (access() == CodeGenState::LOAD) { |
| - __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| - } else { |
| - ASSERT(access() == CodeGenState::LOAD_TYPEOF_EXPR); |
| + if (typeof_state == INSIDE_TYPEOF) { |
| __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| + } else { |
| + __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| } |
| __ push(r0); |
| } else { |
| // Note: We would like to keep the assert below, but it fires because of |
| // some nasty code in LoadTypeofExpression() which should be removed... |
| - // ASSERT(node->var()->mode() != Variable::DYNAMIC); |
| + // ASSERT(slot->var()->mode() != Variable::DYNAMIC); |
| // Special handling for locals allocated in registers. |
| - __ ldr(r0, SlotOperand(node, r2)); |
| + __ ldr(r0, SlotOperand(slot, r2)); |
| __ push(r0); |
| - if (node->var()->mode() == Variable::CONST) { |
| + if (slot->var()->mode() == Variable::CONST) { |
| // Const slots may contain 'the hole' value (the constant hasn't been |
| // initialized yet) which needs to be converted into the 'undefined' |
| // value. |
| @@ -2326,24 +2253,22 @@ |
| } |
| +void ArmCodeGenerator::VisitSlot(Slot* node) { |
| + Comment cmnt(masm_, "[ Slot"); |
| + LoadFromSlot(node, typeof_state()); |
| +} |
| + |
| + |
| void ArmCodeGenerator::VisitVariableProxy(VariableProxy* node) { |
| Comment cmnt(masm_, "[ VariableProxy"); |
| - Variable* var_node = node->var(); |
| - |
| - Expression* expr = var_node->rewrite(); |
| + Variable* var = node->var(); |
| + Expression* expr = var->rewrite(); |
| if (expr != NULL) { |
| Visit(expr); |
| } else { |
| - ASSERT(var_node->is_global()); |
| - if (is_referenced()) { |
| - if (var_node->AsProperty() != NULL) { |
| - __ RecordPosition(var_node->AsProperty()->position()); |
| - } |
| - GetReferenceProperty(new Literal(var_node->name())); |
| - } else { |
| - Reference property(this, node); |
| - GetValue(&property); |
| - } |
| + ASSERT(var->is_global()); |
| + Reference ref(this, node); |
| + ref.GetValue(typeof_state()); |
| } |
| } |
| @@ -2556,7 +2481,7 @@ |
| Load(node->value()); |
| } else { |
| - GetValue(&target); |
| + target.GetValue(NOT_INSIDE_TYPEOF); |
| Literal* literal = node->value()->AsLiteral(); |
| if (literal != NULL && literal->handle()->IsSmi()) { |
| SmiOperation(node->binary_op(), literal->handle(), false); |
| @@ -2601,15 +2526,8 @@ |
| void ArmCodeGenerator::VisitProperty(Property* node) { |
| Comment cmnt(masm_, "[ Property"); |
| - |
| - if (is_referenced()) { |
| - __ RecordPosition(node->position()); |
| - GetReferenceProperty(node->key()); |
| - } else { |
| - Reference property(this, node); |
| - __ RecordPosition(node->position()); |
| - GetValue(&property); |
| - } |
| + Reference property(this, node); |
| + property.GetValue(typeof_state()); |
| } |
| @@ -2713,7 +2631,7 @@ |
| // Load the function to call from the property through a reference. |
| Reference ref(this, property); |
| - GetValue(&ref); // receiver |
| + ref.GetValue(NOT_INSIDE_TYPEOF); // receiver |
| // Pass receiver to called function. |
| __ ldr(r0, MemOperand(sp, ref.size() * kPointerSize)); |
| @@ -2957,7 +2875,7 @@ |
| if (op == Token::NOT) { |
| LoadCondition(node->expression(), |
| - CodeGenState::LOAD, |
| + NOT_INSIDE_TYPEOF, |
| false_target(), |
| true_target(), |
| true); |
| @@ -3092,7 +3010,7 @@ |
| { Reference target(this, node->expression()); |
| if (target.is_illegal()) return; |
| - GetValue(&target); |
| + target.GetValue(NOT_INSIDE_TYPEOF); |
| __ pop(r0); |
| Label slow, exit; |
| @@ -3174,7 +3092,7 @@ |
| if (op == Token::AND) { |
| Label is_true; |
| LoadCondition(node->left(), |
| - CodeGenState::LOAD, |
| + NOT_INSIDE_TYPEOF, |
| &is_true, |
| false_target(), |
| false); |
| @@ -3184,7 +3102,7 @@ |
| // Evaluate right side expression. |
| __ bind(&is_true); |
| LoadCondition(node->right(), |
| - CodeGenState::LOAD, |
| + NOT_INSIDE_TYPEOF, |
| true_target(), |
| false_target(), |
| false); |
| @@ -3215,7 +3133,7 @@ |
| } else if (op == Token::OR) { |
| Label is_false; |
| LoadCondition(node->left(), |
| - CodeGenState::LOAD, |
| + NOT_INSIDE_TYPEOF, |
| true_target(), |
| &is_false, |
| false); |
| @@ -3225,7 +3143,7 @@ |
| // Evaluate right side expression. |
| __ bind(&is_false); |
| LoadCondition(node->right(), |
| - CodeGenState::LOAD, |
| + NOT_INSIDE_TYPEOF, |
| true_target(), |
| false_target(), |
| false); |
| @@ -3517,10 +3435,91 @@ |
| #undef __ |
| #define __ masm-> |
| +Handle<String> Reference::GetName() { |
| + ASSERT(type_ == NAMED); |
| + Property* property = expression_->AsProperty(); |
| + if (property == NULL) { |
| + // Global variable reference treated as a named property reference. |
| + VariableProxy* proxy = expression_->AsVariableProxy(); |
| + ASSERT(proxy->AsVariable() != NULL); |
| + ASSERT(proxy->AsVariable()->is_global()); |
| + return proxy->name(); |
| + } else { |
| + Literal* raw_name = property->key()->AsLiteral(); |
| + ASSERT(raw_name != NULL); |
| + return Handle<String>(String::cast(*raw_name->handle())); |
| + } |
| +} |
| + |
| + |
| +void Reference::GetValue(TypeofState typeof_state) { |
| + ASSERT(!is_illegal()); |
| + ASSERT(!cgen_->has_cc()); |
| + MacroAssembler* masm = cgen_->masm(); |
| + Property* property = expression_->AsProperty(); |
| + if (property != NULL) { |
| + __ RecordPosition(property->position()); |
| + } |
| + |
| + switch (type_) { |
| + case SLOT: { |
| + Comment cmnt(masm, "[ Load from Slot"); |
| + Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); |
| + ASSERT(slot != NULL); |
| + cgen_->LoadFromSlot(slot, typeof_state); |
| + break; |
| + } |
| + |
| + case NAMED: { |
| + // TODO(1241834): Make sure that this it is safe to ignore the |
| + // distinction between expressions ina typeof and not in a typeof. If |
|
iposva
2008/10/07 19:43:31
ina -> in a
|
| + // there is a chance that reference errors can be thrown below, we |
| + // must distinguish between the two kinds of loads (typeof expression |
| + // loads must not throw a reference error). |
| + Comment cmnt(masm, "[ Load from named Property"); |
| + // Setup the name register. |
| + Handle<String> name(GetName()); |
| + __ mov(r2, Operand(name)); |
| + Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| + |
| + Variable* var = expression_->AsVariableProxy()->AsVariable(); |
| + if (var != NULL) { |
| + ASSERT(var->is_global()); |
| + __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| + } else { |
| + __ Call(ic, RelocInfo::CODE_TARGET); |
| + } |
| + __ push(r0); |
| + break; |
| + } |
| + |
| + case KEYED: { |
| + // TODO(1241834): Make sure that this it is safe to ignore the |
| + // distinction between expressions ina typeof and not in a typeof. |
|
iposva
2008/10/07 19:43:31
ina -> in a
|
| + Comment cmnt(masm, "[ Load from keyed Property"); |
| + ASSERT(property != NULL); |
| + // TODO(1224671): Implement inline caching for keyed loads as on ia32. |
| + GetPropertyStub stub; |
| + __ CallStub(&stub); |
| + __ push(r0); |
| + break; |
| + } |
| + |
| + default: |
| + UNREACHABLE(); |
| + } |
| +} |
| + |
| + |
| void Reference::SetValue(InitState init_state) { |
| ASSERT(!is_illegal()); |
| ASSERT(!cgen_->has_cc()); |
| MacroAssembler* masm = cgen_->masm(); |
| + Property* property = expression_->AsProperty(); |
| + if (property != NULL) { |
| + __ RecordPosition(property->position()); |
| + } |
| + |
| switch (type_) { |
| case SLOT: { |
| Comment cmnt(masm, "[ Store to Slot"); |
| @@ -3606,24 +3605,10 @@ |
| case NAMED: { |
| Comment cmnt(masm, "[ Store to named Property"); |
| - Property* property = expression_->AsProperty(); |
| - Handle<String> name; |
| - if (property == NULL) { |
| - // Global variable reference treated as named property access. |
| - VariableProxy* proxy = expression_->AsVariableProxy(); |
| - ASSERT(proxy->AsVariable() != NULL); |
| - ASSERT(proxy->AsVariable()->is_global()); |
| - name = proxy->name(); |
| - } else { |
| - Literal* raw_name = property->key()->AsLiteral(); |
| - ASSERT(raw_name != NULL); |
| - name = Handle<String>(String::cast(*raw_name->handle())); |
| - __ RecordPosition(property->position()); |
| - } |
| - |
| // Call the appropriate IC code. |
| __ pop(r0); // value |
| // Setup the name register. |
| + Handle<String> name(GetName()); |
| __ mov(r2, Operand(name)); |
| Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| __ Call(ic, RelocInfo::CODE_TARGET); |