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

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

Issue 1846002: Refactor assignment in the ARM code generator... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 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') | src/arm/virtual-frame-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 if (false_target.is_linked()) { 558 if (false_target.is_linked()) {
559 false_target.Bind(); 559 false_target.Bind();
560 __ LoadRoot(r0, Heap::kFalseValueRootIndex); 560 __ LoadRoot(r0, Heap::kFalseValueRootIndex);
561 frame_->EmitPush(r0); 561 frame_->EmitPush(r0);
562 } 562 }
563 // A value is loaded on all paths reaching this point. 563 // A value is loaded on all paths reaching this point.
564 loaded.Bind(); 564 loaded.Bind();
565 } 565 }
566 ASSERT(has_valid_frame()); 566 ASSERT(has_valid_frame());
567 ASSERT(!has_cc()); 567 ASSERT(!has_cc());
568 ASSERT(frame_->height() == original_height + 1); 568 ASSERT_EQ(original_height + 1, frame_->height());
569 } 569 }
570 570
571 571
572 void CodeGenerator::LoadGlobal() { 572 void CodeGenerator::LoadGlobal() {
573 Register reg = frame_->GetTOSRegister(); 573 Register reg = frame_->GetTOSRegister();
574 __ ldr(reg, GlobalObject()); 574 __ ldr(reg, GlobalObject());
575 frame_->EmitPush(reg); 575 frame_->EmitPush(reg);
576 } 576 }
577 577
578 578
(...skipping 2131 matching lines...) Expand 10 before | Expand all | Expand 10 after
2710 2710
2711 // Build the function info and instantiate it. 2711 // Build the function info and instantiate it.
2712 Handle<SharedFunctionInfo> function_info = 2712 Handle<SharedFunctionInfo> function_info =
2713 Compiler::BuildFunctionInfo(node, script(), this); 2713 Compiler::BuildFunctionInfo(node, script(), this);
2714 // Check for stack-overflow exception. 2714 // Check for stack-overflow exception.
2715 if (HasStackOverflow()) { 2715 if (HasStackOverflow()) {
2716 ASSERT(frame_->height() == original_height); 2716 ASSERT(frame_->height() == original_height);
2717 return; 2717 return;
2718 } 2718 }
2719 InstantiateFunction(function_info); 2719 InstantiateFunction(function_info);
2720 ASSERT(frame_->height() == original_height + 1); 2720 ASSERT_EQ(original_height + 1, frame_->height());
2721 } 2721 }
2722 2722
2723 2723
2724 void CodeGenerator::VisitSharedFunctionInfoLiteral( 2724 void CodeGenerator::VisitSharedFunctionInfoLiteral(
2725 SharedFunctionInfoLiteral* node) { 2725 SharedFunctionInfoLiteral* node) {
2726 #ifdef DEBUG 2726 #ifdef DEBUG
2727 int original_height = frame_->height(); 2727 int original_height = frame_->height();
2728 #endif 2728 #endif
2729 VirtualFrame::SpilledScope spilled_scope(frame_); 2729 VirtualFrame::SpilledScope spilled_scope(frame_);
2730 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral"); 2730 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
2731 InstantiateFunction(node->shared_function_info()); 2731 InstantiateFunction(node->shared_function_info());
2732 ASSERT(frame_->height() == original_height + 1); 2732 ASSERT_EQ(original_height + 1, frame_->height());
2733 } 2733 }
2734 2734
2735 2735
2736 void CodeGenerator::VisitConditional(Conditional* node) { 2736 void CodeGenerator::VisitConditional(Conditional* node) {
2737 #ifdef DEBUG 2737 #ifdef DEBUG
2738 int original_height = frame_->height(); 2738 int original_height = frame_->height();
2739 #endif 2739 #endif
2740 VirtualFrame::SpilledScope spilled_scope(frame_); 2740 VirtualFrame::SpilledScope spilled_scope(frame_);
2741 Comment cmnt(masm_, "[ Conditional"); 2741 Comment cmnt(masm_, "[ Conditional");
2742 JumpTarget then; 2742 JumpTarget then;
2743 JumpTarget else_; 2743 JumpTarget else_;
2744 LoadConditionAndSpill(node->condition(), &then, &else_, true); 2744 LoadConditionAndSpill(node->condition(), &then, &else_, true);
2745 if (has_valid_frame()) { 2745 if (has_valid_frame()) {
2746 Branch(false, &else_); 2746 Branch(false, &else_);
2747 } 2747 }
2748 if (has_valid_frame() || then.is_linked()) { 2748 if (has_valid_frame() || then.is_linked()) {
2749 then.Bind(); 2749 then.Bind();
2750 LoadAndSpill(node->then_expression()); 2750 LoadAndSpill(node->then_expression());
2751 } 2751 }
2752 if (else_.is_linked()) { 2752 if (else_.is_linked()) {
2753 JumpTarget exit; 2753 JumpTarget exit;
2754 if (has_valid_frame()) exit.Jump(); 2754 if (has_valid_frame()) exit.Jump();
2755 else_.Bind(); 2755 else_.Bind();
2756 LoadAndSpill(node->else_expression()); 2756 LoadAndSpill(node->else_expression());
2757 if (exit.is_linked()) exit.Bind(); 2757 if (exit.is_linked()) exit.Bind();
2758 } 2758 }
2759 ASSERT(frame_->height() == original_height + 1); 2759 ASSERT_EQ(original_height + 1, frame_->height());
2760 } 2760 }
2761 2761
2762 2762
2763 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2763 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2764 if (slot->type() == Slot::LOOKUP) { 2764 if (slot->type() == Slot::LOOKUP) {
2765 ASSERT(slot->var()->is_dynamic()); 2765 ASSERT(slot->var()->is_dynamic());
2766 2766
2767 // JumpTargets do not yet support merging frames so the frame must be 2767 // JumpTargets do not yet support merging frames so the frame must be
2768 // spilled when jumping to these targets. 2768 // spilled when jumping to these targets.
2769 JumpTarget slow; 2769 JumpTarget slow;
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
3021 frame_->Drop(); 3021 frame_->Drop();
3022 } 3022 }
3023 3023
3024 3024
3025 void CodeGenerator::VisitSlot(Slot* node) { 3025 void CodeGenerator::VisitSlot(Slot* node) {
3026 #ifdef DEBUG 3026 #ifdef DEBUG
3027 int original_height = frame_->height(); 3027 int original_height = frame_->height();
3028 #endif 3028 #endif
3029 Comment cmnt(masm_, "[ Slot"); 3029 Comment cmnt(masm_, "[ Slot");
3030 LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF); 3030 LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF);
3031 ASSERT(frame_->height() == original_height + 1); 3031 ASSERT_EQ(original_height + 1, frame_->height());
3032 } 3032 }
3033 3033
3034 3034
3035 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 3035 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
3036 #ifdef DEBUG 3036 #ifdef DEBUG
3037 int original_height = frame_->height(); 3037 int original_height = frame_->height();
3038 #endif 3038 #endif
3039 Comment cmnt(masm_, "[ VariableProxy"); 3039 Comment cmnt(masm_, "[ VariableProxy");
3040 3040
3041 Variable* var = node->var(); 3041 Variable* var = node->var();
3042 Expression* expr = var->rewrite(); 3042 Expression* expr = var->rewrite();
3043 if (expr != NULL) { 3043 if (expr != NULL) {
3044 Visit(expr); 3044 Visit(expr);
3045 } else { 3045 } else {
3046 ASSERT(var->is_global()); 3046 ASSERT(var->is_global());
3047 Reference ref(this, node); 3047 Reference ref(this, node);
3048 ref.GetValue(); 3048 ref.GetValue();
3049 } 3049 }
3050 ASSERT(frame_->height() == original_height + 1); 3050 ASSERT_EQ(original_height + 1, frame_->height());
3051 } 3051 }
3052 3052
3053 3053
3054 void CodeGenerator::VisitLiteral(Literal* node) { 3054 void CodeGenerator::VisitLiteral(Literal* node) {
3055 #ifdef DEBUG 3055 #ifdef DEBUG
3056 int original_height = frame_->height(); 3056 int original_height = frame_->height();
3057 #endif 3057 #endif
3058 Comment cmnt(masm_, "[ Literal"); 3058 Comment cmnt(masm_, "[ Literal");
3059 Register reg = frame_->GetTOSRegister(); 3059 Register reg = frame_->GetTOSRegister();
3060 __ mov(reg, Operand(node->handle())); 3060 __ mov(reg, Operand(node->handle()));
3061 frame_->EmitPush(reg); 3061 frame_->EmitPush(reg);
3062 ASSERT(frame_->height() == original_height + 1); 3062 ASSERT_EQ(original_height + 1, frame_->height());
3063 } 3063 }
3064 3064
3065 3065
3066 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 3066 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
3067 #ifdef DEBUG 3067 #ifdef DEBUG
3068 int original_height = frame_->height(); 3068 int original_height = frame_->height();
3069 #endif 3069 #endif
3070 VirtualFrame::SpilledScope spilled_scope(frame_); 3070 VirtualFrame::SpilledScope spilled_scope(frame_);
3071 Comment cmnt(masm_, "[ RexExp Literal"); 3071 Comment cmnt(masm_, "[ RexExp Literal");
3072 3072
(...skipping 23 matching lines...) Expand all
3096 __ mov(r0, Operand(node->pattern())); // RegExp pattern (2) 3096 __ mov(r0, Operand(node->pattern())); // RegExp pattern (2)
3097 frame_->EmitPush(r0); 3097 frame_->EmitPush(r0);
3098 __ mov(r0, Operand(node->flags())); // RegExp flags (3) 3098 __ mov(r0, Operand(node->flags())); // RegExp flags (3)
3099 frame_->EmitPush(r0); 3099 frame_->EmitPush(r0);
3100 frame_->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 3100 frame_->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
3101 __ mov(r2, Operand(r0)); 3101 __ mov(r2, Operand(r0));
3102 3102
3103 done.Bind(); 3103 done.Bind();
3104 // Push the literal. 3104 // Push the literal.
3105 frame_->EmitPush(r2); 3105 frame_->EmitPush(r2);
3106 ASSERT(frame_->height() == original_height + 1); 3106 ASSERT_EQ(original_height + 1, frame_->height());
3107 } 3107 }
3108 3108
3109 3109
3110 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 3110 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
3111 #ifdef DEBUG 3111 #ifdef DEBUG
3112 int original_height = frame_->height(); 3112 int original_height = frame_->height();
3113 #endif 3113 #endif
3114 VirtualFrame::SpilledScope spilled_scope(frame_); 3114 VirtualFrame::SpilledScope spilled_scope(frame_);
3115 Comment cmnt(masm_, "[ ObjectLiteral"); 3115 Comment cmnt(masm_, "[ ObjectLiteral");
3116 3116
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
3177 frame_->EmitPush(r0); 3177 frame_->EmitPush(r0);
3178 LoadAndSpill(key); 3178 LoadAndSpill(key);
3179 __ mov(r0, Operand(Smi::FromInt(0))); 3179 __ mov(r0, Operand(Smi::FromInt(0)));
3180 frame_->EmitPush(r0); 3180 frame_->EmitPush(r0);
3181 LoadAndSpill(value); 3181 LoadAndSpill(value);
3182 frame_->CallRuntime(Runtime::kDefineAccessor, 4); 3182 frame_->CallRuntime(Runtime::kDefineAccessor, 4);
3183 break; 3183 break;
3184 } 3184 }
3185 } 3185 }
3186 } 3186 }
3187 ASSERT(frame_->height() == original_height + 1); 3187 ASSERT_EQ(original_height + 1, frame_->height());
3188 } 3188 }
3189 3189
3190 3190
3191 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 3191 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
3192 #ifdef DEBUG 3192 #ifdef DEBUG
3193 int original_height = frame_->height(); 3193 int original_height = frame_->height();
3194 #endif 3194 #endif
3195 VirtualFrame::SpilledScope spilled_scope(frame_); 3195 VirtualFrame::SpilledScope spilled_scope(frame_);
3196 Comment cmnt(masm_, "[ ArrayLiteral"); 3196 Comment cmnt(masm_, "[ ArrayLiteral");
3197 3197
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3236 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); 3236 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
3237 3237
3238 // Write to the indexed properties array. 3238 // Write to the indexed properties array.
3239 int offset = i * kPointerSize + FixedArray::kHeaderSize; 3239 int offset = i * kPointerSize + FixedArray::kHeaderSize;
3240 __ str(r0, FieldMemOperand(r1, offset)); 3240 __ str(r0, FieldMemOperand(r1, offset));
3241 3241
3242 // Update the write barrier for the array address. 3242 // Update the write barrier for the array address.
3243 __ mov(r3, Operand(offset)); 3243 __ mov(r3, Operand(offset));
3244 __ RecordWrite(r1, r3, r2); 3244 __ RecordWrite(r1, r3, r2);
3245 } 3245 }
3246 ASSERT(frame_->height() == original_height + 1); 3246 ASSERT_EQ(original_height + 1, frame_->height());
3247 } 3247 }
3248 3248
3249 3249
3250 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { 3250 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) {
3251 #ifdef DEBUG 3251 #ifdef DEBUG
3252 int original_height = frame_->height(); 3252 int original_height = frame_->height();
3253 #endif 3253 #endif
3254 VirtualFrame::SpilledScope spilled_scope(frame_); 3254 VirtualFrame::SpilledScope spilled_scope(frame_);
3255 // Call runtime routine to allocate the catch extension object and 3255 // Call runtime routine to allocate the catch extension object and
3256 // assign the exception value to the catch variable. 3256 // assign the exception value to the catch variable.
3257 Comment cmnt(masm_, "[ CatchExtensionObject"); 3257 Comment cmnt(masm_, "[ CatchExtensionObject");
3258 LoadAndSpill(node->key()); 3258 LoadAndSpill(node->key());
3259 LoadAndSpill(node->value()); 3259 LoadAndSpill(node->value());
3260 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); 3260 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
3261 frame_->EmitPush(r0); 3261 frame_->EmitPush(r0);
3262 ASSERT(frame_->height() == original_height + 1); 3262 ASSERT_EQ(original_height + 1, frame_->height());
3263 }
3264
3265
3266 void CodeGenerator::EmitSlotAssignment(Assignment* node) {
3267 #ifdef DEBUG
3268 int original_height = frame_->height();
3269 #endif
3270 Comment cmnt(masm(), "[ Variable Assignment");
3271 Variable* var = node->target()->AsVariableProxy()->AsVariable();
3272 ASSERT(var != NULL);
3273 Slot* slot = var->slot();
3274 ASSERT(slot != NULL);
3275
3276 // Evaluate the right-hand side.
3277 if (node->is_compound()) {
3278 // For a compound assignment the right-hand side is a binary operation
3279 // between the current property value and the actual right-hand side.
3280 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
3281
3282 // Perform the binary operation.
3283 Literal* literal = node->value()->AsLiteral();
3284 bool overwrite_value =
3285 (node->value()->AsBinaryOperation() != NULL &&
3286 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
3287 if (literal != NULL && literal->handle()->IsSmi()) {
3288 SmiOperation(node->binary_op(),
3289 literal->handle(),
3290 false,
3291 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
3292 } else {
3293 Load(node->value());
3294 VirtualFrameBinaryOperation(
3295 node->binary_op(), overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
3296 }
3297 } else {
3298 Load(node->value());
3299 }
3300
3301 // Perform the assignment.
3302 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) {
3303 CodeForSourcePosition(node->position());
3304 StoreToSlot(slot,
3305 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT);
3306 }
3307 ASSERT_EQ(original_height + 1, frame_->height());
3308 }
3309
3310
3311 void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
3312 #ifdef DEBUG
3313 int original_height = frame_->height();
3314 #endif
3315 Comment cmnt(masm(), "[ Named Property Assignment");
3316 Variable* var = node->target()->AsVariableProxy()->AsVariable();
3317 Property* prop = node->target()->AsProperty();
3318 ASSERT(var == NULL || (prop == NULL && var->is_global()));
3319
3320 // Initialize name and evaluate the receiver sub-expression if necessary. If
3321 // the receiver is trivial it is not placed on the stack at this point, but
3322 // loaded whenever actually needed.
3323 Handle<String> name;
3324 bool is_trivial_receiver = false;
3325 if (var != NULL) {
3326 name = var->name();
3327 } else {
3328 Literal* lit = prop->key()->AsLiteral();
3329 ASSERT_NOT_NULL(lit);
3330 name = Handle<String>::cast(lit->handle());
3331 // Do not materialize the receiver on the frame if it is trivial.
3332 is_trivial_receiver = prop->obj()->IsTrivial();
3333 if (!is_trivial_receiver) Load(prop->obj());
3334 }
3335
3336 // Change to slow case in the beginning of an initialization block to
3337 // avoid the quadratic behavior of repeatedly adding fast properties.
3338 if (node->starts_initialization_block()) {
3339 // Initialization block consists of assignments on the form expr.x = ..., so
3340 // this will never be an assignment to a variable, so there must be a
3341 // receiver object.
3342 ASSERT_EQ(NULL, var);
3343 if (is_trivial_receiver) {
3344 Load(prop->obj());
3345 } else {
3346 frame_->Dup();
3347 }
3348 frame_->CallRuntime(Runtime::kToSlowProperties, 1);
3349 }
3350
3351 // Change to fast case at the end of an initialization block. To prepare for
3352 // that add an extra copy of the receiver to the frame, so that it can be
3353 // converted back to fast case after the assignment.
3354 if (node->ends_initialization_block() && !is_trivial_receiver) {
3355 frame_->Dup();
3356 }
3357
3358 // Stack layout:
3359 // [tos] : receiver (only materialized if non-trivial)
3360 // [tos+1] : receiver if at the end of an initialization block
3361
3362 // Evaluate the right-hand side.
3363 if (node->is_compound()) {
3364 // For a compound assignment the right-hand side is a binary operation
3365 // between the current property value and the actual right-hand side.
3366 if (is_trivial_receiver) {
3367 Load(prop->obj());
3368 } else if (var != NULL) {
3369 LoadGlobal();
3370 } else {
3371 frame_->Dup();
3372 }
3373 EmitNamedLoad(name, var != NULL);
3374 frame_->Drop(); // Receiver is left on the stack.
3375 frame_->EmitPush(r0);
3376
3377 // Perform the binary operation.
3378 Literal* literal = node->value()->AsLiteral();
3379 bool overwrite_value =
3380 (node->value()->AsBinaryOperation() != NULL &&
3381 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
3382 if (literal != NULL && literal->handle()->IsSmi()) {
3383 SmiOperation(node->binary_op(),
3384 literal->handle(),
3385 false,
3386 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
3387 } else {
3388 Load(node->value());
3389 VirtualFrameBinaryOperation(
3390 node->binary_op(), overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
3391 }
3392 } else {
3393 // For non-compound assignment just load the right-hand side.
3394 Load(node->value());
3395 }
3396
3397 // Stack layout:
3398 // [tos] : value
3399 // [tos+1] : receiver (only materialized if non-trivial)
3400 // [tos+2] : receiver if at the end of an initialization block
3401
3402 // Perform the assignment. It is safe to ignore constants here.
3403 ASSERT(var == NULL || var->mode() != Variable::CONST);
3404 ASSERT_NE(Token::INIT_CONST, node->op());
3405 if (is_trivial_receiver) {
3406 // Load the receiver and swap with the value.
3407 Load(prop->obj());
3408 Register t0 = frame_->PopToRegister();
3409 Register t1 = frame_->PopToRegister(t0);
3410 frame_->EmitPush(t0);
3411 frame_->EmitPush(t1);
3412 }
3413 CodeForSourcePosition(node->position());
3414 bool is_contextual = (var != NULL);
3415 EmitNamedStore(name, is_contextual);
3416 frame_->EmitPush(r0);
3417
3418 // Change to fast case at the end of an initialization block.
3419 if (node->ends_initialization_block()) {
3420 ASSERT_EQ(NULL, var);
3421 // The argument to the runtime call is the receiver.
3422 if (is_trivial_receiver) {
3423 Load(prop->obj());
3424 } else {
3425 // A copy of the receiver is below the value of the assignment. Swap
3426 // the receiver and the value of the assignment expression.
3427 Register t0 = frame_->PopToRegister();
3428 Register t1 = frame_->PopToRegister(t0);
3429 frame_->EmitPush(t0);
3430 frame_->EmitPush(t1);
3431 }
3432 frame_->CallRuntime(Runtime::kToFastProperties, 1);
3433 }
3434
3435 // Stack layout:
3436 // [tos] : result
3437
3438 ASSERT_EQ(original_height + 1, frame_->height());
3439 }
3440
3441
3442 void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
3443 #ifdef DEBUG
3444 int original_height = frame_->height();
3445 #endif
3446 Comment cmnt(masm_, "[ Keyed Property Assignment");
3447 Property* prop = node->target()->AsProperty();
3448 ASSERT_NOT_NULL(prop);
3449
3450 // Evaluate the receiver subexpression.
3451 Load(prop->obj());
3452
3453 // Change to slow case in the beginning of an initialization block to
3454 // avoid the quadratic behavior of repeatedly adding fast properties.
3455 if (node->starts_initialization_block()) {
3456 frame_->Dup();
3457 frame_->CallRuntime(Runtime::kToSlowProperties, 1);
3458 }
3459
3460 // Change to fast case at the end of an initialization block. To prepare for
3461 // that add an extra copy of the receiver to the frame, so that it can be
3462 // converted back to fast case after the assignment.
3463 if (node->ends_initialization_block()) {
3464 frame_->Dup();
3465 }
3466
3467 // Evaluate the key subexpression.
3468 Load(prop->key());
3469
3470 // Stack layout:
3471 // [tos] : key
3472 // [tos+1] : receiver
3473 // [tos+2] : receiver if at the end of an initialization block
3474
3475 // Evaluate the right-hand side.
3476 if (node->is_compound()) {
3477 // For a compound assignment the right-hand side is a binary operation
3478 // between the current property value and the actual right-hand side.
3479 // Load of the current value leaves receiver and key on the stack.
3480 EmitKeyedLoad();
3481 frame_->EmitPush(r0);
3482
3483 // Perform the binary operation.
3484 Literal* literal = node->value()->AsLiteral();
3485 bool overwrite_value =
3486 (node->value()->AsBinaryOperation() != NULL &&
3487 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
3488 if (literal != NULL && literal->handle()->IsSmi()) {
3489 SmiOperation(node->binary_op(),
3490 literal->handle(),
3491 false,
3492 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
3493 } else {
3494 Load(node->value());
3495 VirtualFrameBinaryOperation(
3496 node->binary_op(), overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
3497 }
3498 } else {
3499 // For non-compound assignment just load the right-hand side.
3500 Load(node->value());
3501 }
3502
3503 // Stack layout:
3504 // [tos] : value
3505 // [tos+1] : key
3506 // [tos+2] : receiver
3507 // [tos+3] : receiver if at the end of an initialization block
3508
3509 // Perform the assignment. It is safe to ignore constants here.
3510 ASSERT(node->op() != Token::INIT_CONST);
3511 CodeForSourcePosition(node->position());
3512 frame_->PopToR0();
3513 EmitKeyedStore(prop->key()->type());
3514 frame_->Drop(2); // Key and receiver are left on the stack.
3515 frame_->EmitPush(r0);
3516
3517 // Stack layout:
3518 // [tos] : result
3519 // [tos+1] : receiver if at the end of an initialization block
3520
3521 // Change to fast case at the end of an initialization block.
3522 if (node->ends_initialization_block()) {
3523 // The argument to the runtime call is the extra copy of the receiver,
3524 // which is below the value of the assignment. Swap the receiver and
3525 // the value of the assignment expression.
3526 Register t0 = frame_->PopToRegister();
3527 Register t1 = frame_->PopToRegister(t0);
3528 frame_->EmitPush(t1);
3529 frame_->EmitPush(t0);
3530 frame_->CallRuntime(Runtime::kToFastProperties, 1);
3531 }
3532
3533 // Stack layout:
3534 // [tos] : result
3535
3536 ASSERT_EQ(original_height + 1, frame_->height());
3263 } 3537 }
3264 3538
3265 3539
3266 void CodeGenerator::VisitAssignment(Assignment* node) { 3540 void CodeGenerator::VisitAssignment(Assignment* node) {
3267 VirtualFrame::RegisterAllocationScope scope(this); 3541 VirtualFrame::RegisterAllocationScope scope(this);
3268 #ifdef DEBUG 3542 #ifdef DEBUG
3269 int original_height = frame_->height(); 3543 int original_height = frame_->height();
3270 #endif 3544 #endif
3271 Comment cmnt(masm_, "[ Assignment"); 3545 Comment cmnt(masm_, "[ Assignment");
3272 3546
3273 { Reference target(this, node->target(), node->is_compound()); 3547 Variable* var = node->target()->AsVariableProxy()->AsVariable();
3274 if (target.is_illegal()) { 3548 Property* prop = node->target()->AsProperty();
3275 // Fool the virtual frame into thinking that we left the assignment's 3549
3276 // value on the frame. 3550 if (var != NULL && !var->is_global()) {
3277 Register tos = frame_->GetTOSRegister(); 3551 EmitSlotAssignment(node);
3278 __ mov(tos, Operand(Smi::FromInt(0))); 3552
3279 frame_->EmitPush(tos); 3553 } else if ((prop != NULL && prop->key()->IsPropertyName()) ||
3280 ASSERT(frame_->height() == original_height + 1); 3554 (var != NULL && var->is_global())) {
3281 return; 3555 // Properties whose keys are property names and global variables are
3282 } 3556 // treated as named property references. We do not need to consider
3283 3557 // global 'this' because it is not a valid left-hand side.
3284 if (node->op() == Token::ASSIGN || 3558 EmitNamedPropertyAssignment(node);
3285 node->op() == Token::INIT_VAR || 3559
3286 node->op() == Token::INIT_CONST) { 3560 } else if (prop != NULL) {
3287 Load(node->value()); 3561 // Other properties (including rewritten parameters for a function that
3288 3562 // uses arguments) are keyed property assignments.
3289 } else { // Assignment is a compound assignment. 3563 EmitKeyedPropertyAssignment(node);
3290 // Get the old value of the lhs. 3564
3291 target.GetValue(); 3565 } else {
3292 Literal* literal = node->value()->AsLiteral(); 3566 // Invalid left-hand side.
3293 bool overwrite = 3567 Load(node->target());
3294 (node->value()->AsBinaryOperation() != NULL && 3568 frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
3295 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 3569 // The runtime call doesn't actually return but the code generator will
3296 if (literal != NULL && literal->handle()->IsSmi()) { 3570 // still generate code and expects a certain frame height.
3297 SmiOperation(node->binary_op(), 3571 frame_->EmitPush(r0);
3298 literal->handle(), 3572 }
3299 false, 3573 ASSERT_EQ(original_height + 1, frame_->height());
3300 overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE);
3301 } else {
3302 Load(node->value());
3303 VirtualFrameBinaryOperation(node->binary_op(),
3304 overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE);
3305 }
3306 }
3307 Variable* var = node->target()->AsVariableProxy()->AsVariable();
3308 if (var != NULL &&
3309 (var->mode() == Variable::CONST) &&
3310 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
3311 // Assignment ignored - leave the value on the stack.
3312 UnloadReference(&target);
3313 } else {
3314 CodeForSourcePosition(node->position());
3315 if (node->op() == Token::INIT_CONST) {
3316 // Dynamic constant initializations must use the function context
3317 // and initialize the actual constant declared. Dynamic variable
3318 // initializations are simply assignments and use SetValue.
3319 target.SetValue(CONST_INIT);
3320 } else {
3321 target.SetValue(NOT_CONST_INIT);
3322 }
3323 }
3324 }
3325 ASSERT(frame_->height() == original_height + 1);
3326 } 3574 }
3327 3575
3328 3576
3329 void CodeGenerator::VisitThrow(Throw* node) { 3577 void CodeGenerator::VisitThrow(Throw* node) {
3330 #ifdef DEBUG 3578 #ifdef DEBUG
3331 int original_height = frame_->height(); 3579 int original_height = frame_->height();
3332 #endif 3580 #endif
3333 VirtualFrame::SpilledScope spilled_scope(frame_); 3581 VirtualFrame::SpilledScope spilled_scope(frame_);
3334 Comment cmnt(masm_, "[ Throw"); 3582 Comment cmnt(masm_, "[ Throw");
3335 3583
3336 LoadAndSpill(node->exception()); 3584 LoadAndSpill(node->exception());
3337 CodeForSourcePosition(node->position()); 3585 CodeForSourcePosition(node->position());
3338 frame_->CallRuntime(Runtime::kThrow, 1); 3586 frame_->CallRuntime(Runtime::kThrow, 1);
3339 frame_->EmitPush(r0); 3587 frame_->EmitPush(r0);
3340 ASSERT(frame_->height() == original_height + 1); 3588 ASSERT_EQ(original_height + 1, frame_->height());
3341 } 3589 }
3342 3590
3343 3591
3344 void CodeGenerator::VisitProperty(Property* node) { 3592 void CodeGenerator::VisitProperty(Property* node) {
3345 #ifdef DEBUG 3593 #ifdef DEBUG
3346 int original_height = frame_->height(); 3594 int original_height = frame_->height();
3347 #endif 3595 #endif
3348 Comment cmnt(masm_, "[ Property"); 3596 Comment cmnt(masm_, "[ Property");
3349 3597
3350 { Reference property(this, node); 3598 { Reference property(this, node);
3351 property.GetValue(); 3599 property.GetValue();
3352 } 3600 }
3353 ASSERT(frame_->height() == original_height + 1); 3601 ASSERT_EQ(original_height + 1, frame_->height());
3354 } 3602 }
3355 3603
3356 3604
3357 void CodeGenerator::VisitCall(Call* node) { 3605 void CodeGenerator::VisitCall(Call* node) {
3358 #ifdef DEBUG 3606 #ifdef DEBUG
3359 int original_height = frame_->height(); 3607 int original_height = frame_->height();
3360 #endif 3608 #endif
3361 VirtualFrame::SpilledScope spilled_scope(frame_); 3609 VirtualFrame::SpilledScope spilled_scope(frame_);
3362 Comment cmnt(masm_, "[ Call"); 3610 Comment cmnt(masm_, "[ Call");
3363 3611
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
3550 // Load the function. 3798 // Load the function.
3551 LoadAndSpill(function); 3799 LoadAndSpill(function);
3552 3800
3553 // Pass the global proxy as the receiver. 3801 // Pass the global proxy as the receiver.
3554 LoadGlobalReceiver(r0); 3802 LoadGlobalReceiver(r0);
3555 3803
3556 // Call the function. 3804 // Call the function.
3557 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); 3805 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position());
3558 frame_->EmitPush(r0); 3806 frame_->EmitPush(r0);
3559 } 3807 }
3560 ASSERT(frame_->height() == original_height + 1); 3808 ASSERT_EQ(original_height + 1, frame_->height());
3561 } 3809 }
3562 3810
3563 3811
3564 void CodeGenerator::VisitCallNew(CallNew* node) { 3812 void CodeGenerator::VisitCallNew(CallNew* node) {
3565 #ifdef DEBUG 3813 #ifdef DEBUG
3566 int original_height = frame_->height(); 3814 int original_height = frame_->height();
3567 #endif 3815 #endif
3568 VirtualFrame::SpilledScope spilled_scope(frame_); 3816 VirtualFrame::SpilledScope spilled_scope(frame_);
3569 Comment cmnt(masm_, "[ CallNew"); 3817 Comment cmnt(masm_, "[ CallNew");
3570 3818
(...skipping 22 matching lines...) Expand all
3593 __ ldr(r1, frame_->ElementAt(arg_count + 1)); 3841 __ ldr(r1, frame_->ElementAt(arg_count + 1));
3594 3842
3595 // Call the construct call builtin that handles allocation and 3843 // Call the construct call builtin that handles allocation and
3596 // constructor invocation. 3844 // constructor invocation.
3597 CodeForSourcePosition(node->position()); 3845 CodeForSourcePosition(node->position());
3598 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); 3846 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
3599 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1); 3847 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1);
3600 3848
3601 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). 3849 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
3602 __ str(r0, frame_->Top()); 3850 __ str(r0, frame_->Top());
3603 ASSERT(frame_->height() == original_height + 1); 3851 ASSERT_EQ(original_height + 1, frame_->height());
3604 } 3852 }
3605 3853
3606 3854
3607 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { 3855 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) {
3608 VirtualFrame::SpilledScope spilled_scope(frame_); 3856 VirtualFrame::SpilledScope spilled_scope(frame_);
3609 ASSERT(args->length() == 1); 3857 ASSERT(args->length() == 1);
3610 JumpTarget leave, null, function, non_function_constructor; 3858 JumpTarget leave, null, function, non_function_constructor;
3611 3859
3612 // Load the object into r0. 3860 // Load the object into r0.
3613 LoadAndSpill(args->at(0)); 3861 LoadAndSpill(args->at(0));
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after
4418 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; 4666 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
4419 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); 4667 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
4420 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); 4668 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
4421 __ ldr(cp, frame_->Context()); 4669 __ ldr(cp, frame_->Context());
4422 frame_->EmitPush(r0); 4670 frame_->EmitPush(r0);
4423 } else { 4671 } else {
4424 // Call the C runtime function. 4672 // Call the C runtime function.
4425 frame_->CallRuntime(function, arg_count); 4673 frame_->CallRuntime(function, arg_count);
4426 frame_->EmitPush(r0); 4674 frame_->EmitPush(r0);
4427 } 4675 }
4428 ASSERT(frame_->height() == original_height + 1); 4676 ASSERT_EQ(original_height + 1, frame_->height());
4429 } 4677 }
4430 4678
4431 4679
4432 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 4680 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
4433 #ifdef DEBUG 4681 #ifdef DEBUG
4434 int original_height = frame_->height(); 4682 int original_height = frame_->height();
4435 #endif 4683 #endif
4436 VirtualFrame::SpilledScope spilled_scope(frame_); 4684 VirtualFrame::SpilledScope spilled_scope(frame_);
4437 Comment cmnt(masm_, "[ UnaryOperation"); 4685 Comment cmnt(masm_, "[ UnaryOperation");
4438 4686
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
4582 // A constant reference is not saved to, so a constant reference is not a 4830 // A constant reference is not saved to, so a constant reference is not a
4583 // compound assignment reference. 4831 // compound assignment reference.
4584 { Reference target(this, node->expression(), !is_const); 4832 { Reference target(this, node->expression(), !is_const);
4585 if (target.is_illegal()) { 4833 if (target.is_illegal()) {
4586 // Spoof the virtual frame to have the expected height (one higher 4834 // Spoof the virtual frame to have the expected height (one higher
4587 // than on entry). 4835 // than on entry).
4588 if (!is_postfix) { 4836 if (!is_postfix) {
4589 __ mov(r0, Operand(Smi::FromInt(0))); 4837 __ mov(r0, Operand(Smi::FromInt(0)));
4590 frame_->EmitPush(r0); 4838 frame_->EmitPush(r0);
4591 } 4839 }
4592 ASSERT(frame_->height() == original_height + 1); 4840 ASSERT_EQ(original_height + 1, frame_->height());
4593 return; 4841 return;
4594 } 4842 }
4595 target.GetValue(); 4843 target.GetValue();
4596 frame_->EmitPop(r0); 4844 frame_->EmitPop(r0);
4597 4845
4598 JumpTarget slow; 4846 JumpTarget slow;
4599 JumpTarget exit; 4847 JumpTarget exit;
4600 4848
4601 // Load the value (1) into register r1. 4849 // Load the value (1) into register r1.
4602 __ mov(r1, Operand(Smi::FromInt(1))); 4850 __ mov(r1, Operand(Smi::FromInt(1)));
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
4650 } 4898 }
4651 4899
4652 // Store the new value in the target if not const. 4900 // Store the new value in the target if not const.
4653 exit.Bind(); 4901 exit.Bind();
4654 frame_->EmitPush(r0); 4902 frame_->EmitPush(r0);
4655 if (!is_const) target.SetValue(NOT_CONST_INIT); 4903 if (!is_const) target.SetValue(NOT_CONST_INIT);
4656 } 4904 }
4657 4905
4658 // Postfix: Discard the new value and use the old. 4906 // Postfix: Discard the new value and use the old.
4659 if (is_postfix) frame_->EmitPop(r0); 4907 if (is_postfix) frame_->EmitPop(r0);
4660 ASSERT(frame_->height() == original_height + 1); 4908 ASSERT_EQ(original_height + 1, frame_->height());
4661 } 4909 }
4662 4910
4663 4911
4664 void CodeGenerator::GenerateLogicalBooleanOperation(BinaryOperation* node) { 4912 void CodeGenerator::GenerateLogicalBooleanOperation(BinaryOperation* node) {
4665 // According to ECMA-262 section 11.11, page 58, the binary logical 4913 // According to ECMA-262 section 11.11, page 58, the binary logical
4666 // operators must yield the result of one of the two expressions 4914 // operators must yield the result of one of the two expressions
4667 // before any ToBoolean() conversions. This means that the value 4915 // before any ToBoolean() conversions. This means that the value
4668 // produced by a && or || operator is not necessarily a boolean. 4916 // produced by a && or || operator is not necessarily a boolean.
4669 4917
4670 // NOTE: If the left hand side produces a materialized value (not in 4918 // NOTE: If the left hand side produces a materialized value (not in
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
4825 } 5073 }
4826 5074
4827 5075
4828 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 5076 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
4829 #ifdef DEBUG 5077 #ifdef DEBUG
4830 int original_height = frame_->height(); 5078 int original_height = frame_->height();
4831 #endif 5079 #endif
4832 VirtualFrame::SpilledScope spilled_scope(frame_); 5080 VirtualFrame::SpilledScope spilled_scope(frame_);
4833 __ ldr(r0, frame_->Function()); 5081 __ ldr(r0, frame_->Function());
4834 frame_->EmitPush(r0); 5082 frame_->EmitPush(r0);
4835 ASSERT(frame_->height() == original_height + 1); 5083 ASSERT_EQ(original_height + 1, frame_->height());
4836 } 5084 }
4837 5085
4838 5086
4839 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { 5087 void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
4840 #ifdef DEBUG 5088 #ifdef DEBUG
4841 int original_height = frame_->height(); 5089 int original_height = frame_->height();
4842 #endif 5090 #endif
4843 Comment cmnt(masm_, "[ CompareOperation"); 5091 Comment cmnt(masm_, "[ CompareOperation");
4844 5092
4845 VirtualFrame::RegisterAllocationScope nonspilled_scope(this); 5093 VirtualFrame::RegisterAllocationScope nonspilled_scope(this);
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
5219 // Make sure that the expected number of instructions are generated. 5467 // Make sure that the expected number of instructions are generated.
5220 ASSERT_EQ(kInlinedNamedLoadInstructions, 5468 ASSERT_EQ(kInlinedNamedLoadInstructions,
5221 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); 5469 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
5222 } 5470 }
5223 5471
5224 deferred->BindExit(); 5472 deferred->BindExit();
5225 } 5473 }
5226 } 5474 }
5227 5475
5228 5476
5477 void CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
5478 #ifdef DEBUG
5479 int expected_height = frame_->height() - (is_contextual ? 1 : 2);
5480 #endif
5481 frame_->CallStoreIC(name, is_contextual);
5482
5483 ASSERT_EQ(expected_height, frame_->height());
5484 }
5485
5486
5229 void CodeGenerator::EmitKeyedLoad() { 5487 void CodeGenerator::EmitKeyedLoad() {
5230 if (loop_nesting() == 0) { 5488 if (loop_nesting() == 0) {
5231 VirtualFrame::SpilledScope spilled(frame_); 5489 VirtualFrame::SpilledScope spilled(frame_);
5232 Comment cmnt(masm_, "[ Load from keyed property"); 5490 Comment cmnt(masm_, "[ Load from keyed property");
5233 frame_->CallKeyedLoadIC(); 5491 frame_->CallKeyedLoadIC();
5234 } else { 5492 } else {
5235 // Inline the keyed load. 5493 // Inline the keyed load.
5236 Comment cmnt(masm_, "[ Inlined load from keyed property"); 5494 Comment cmnt(masm_, "[ Inlined load from keyed property");
5237 5495
5238 // Counter will be decremented in the deferred code. Placed here to avoid 5496 // Counter will be decremented in the deferred code. Placed here to avoid
5239 // having it in the instruction stream below where patching will occur. 5497 // having it in the instruction stream below where patching will occur.
5240 __ IncrementCounter(&Counters::keyed_load_inline, 1, 5498 __ IncrementCounter(&Counters::keyed_load_inline, 1,
5241 frame_->scratch0(), frame_->scratch1()); 5499 frame_->scratch0(), frame_->scratch1());
5242 5500
5243 // Load the receiver and key from the stack. 5501 // Load the receiver and key from the stack.
5244 frame_->SpillAllButCopyTOSToR1R0(); 5502 frame_->SpillAllButCopyTOSToR1R0();
5245 Register receiver = r0; 5503 Register receiver = r0;
5246 Register key = r1; 5504 Register key = r1;
5247 VirtualFrame::SpilledScope spilled(frame_); 5505 VirtualFrame::SpilledScope spilled(frame_);
5248 5506
5249 DeferredReferenceGetKeyedValue* deferred = 5507 DeferredReferenceGetKeyedValue* deferred =
5250 new DeferredReferenceGetKeyedValue(); 5508 new DeferredReferenceGetKeyedValue();
5251 5509
5252 // Check that the receiver is a heap object. 5510 // Check that the receiver is a heap object.
5253 __ tst(receiver, Operand(kSmiTagMask)); 5511 __ tst(receiver, Operand(kSmiTagMask));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
5308 ASSERT_EQ(kInlinedKeyedLoadInstructions, 5566 ASSERT_EQ(kInlinedKeyedLoadInstructions,
5309 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); 5567 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
5310 } 5568 }
5311 5569
5312 deferred->BindExit(); 5570 deferred->BindExit();
5313 } 5571 }
5314 } 5572 }
5315 5573
5316 5574
5317 void CodeGenerator::EmitKeyedStore(StaticType* key_type) { 5575 void CodeGenerator::EmitKeyedStore(StaticType* key_type) {
5318 frame_->AssertIsSpilled(); 5576 VirtualFrame::SpilledScope scope(frame_);
5319 // Generate inlined version of the keyed store if the code is in a loop 5577 // Generate inlined version of the keyed store if the code is in a loop
5320 // and the key is likely to be a smi. 5578 // and the key is likely to be a smi.
5321 if (loop_nesting() > 0 && key_type->IsLikelySmi()) { 5579 if (loop_nesting() > 0 && key_type->IsLikelySmi()) {
5322 // Inline the keyed store. 5580 // Inline the keyed store.
5323 Comment cmnt(masm_, "[ Inlined store to keyed property"); 5581 Comment cmnt(masm_, "[ Inlined store to keyed property");
5324 5582
5325 DeferredReferenceSetKeyedValue* deferred = 5583 DeferredReferenceSetKeyedValue* deferred =
5326 new DeferredReferenceSetKeyedValue(); 5584 new DeferredReferenceSetKeyedValue();
5327 5585
5328 // Counter will be decremented in the deferred code. Placed here to avoid 5586 // Counter will be decremented in the deferred code. Placed here to avoid
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
5476 Property* property = expression_->AsProperty(); 5734 Property* property = expression_->AsProperty();
5477 if (property != NULL) { 5735 if (property != NULL) {
5478 cgen_->CodeForSourcePosition(property->position()); 5736 cgen_->CodeForSourcePosition(property->position());
5479 } 5737 }
5480 5738
5481 switch (type_) { 5739 switch (type_) {
5482 case SLOT: { 5740 case SLOT: {
5483 Comment cmnt(masm, "[ Store to Slot"); 5741 Comment cmnt(masm, "[ Store to Slot");
5484 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 5742 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
5485 cgen_->StoreToSlot(slot, init_state); 5743 cgen_->StoreToSlot(slot, init_state);
5486 cgen_->UnloadReference(this); 5744 set_unloaded();
5487 break; 5745 break;
5488 } 5746 }
5489 5747
5490 case NAMED: { 5748 case NAMED: {
5491 VirtualFrame::SpilledScope scope(frame);
5492 Comment cmnt(masm, "[ Store to named Property"); 5749 Comment cmnt(masm, "[ Store to named Property");
5493 // Call the appropriate IC code. 5750 cgen_->EmitNamedStore(GetName(), false);
5494 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
5495 Handle<String> name(GetName());
5496
5497 frame->EmitPop(r0);
5498 frame->EmitPop(r1);
5499 __ mov(r2, Operand(name));
5500 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
5501 frame->EmitPush(r0); 5751 frame->EmitPush(r0);
5502 set_unloaded(); 5752 set_unloaded();
5503 break; 5753 break;
5504 } 5754 }
5505 5755
5506 case KEYED: { 5756 case KEYED: {
5507 VirtualFrame::SpilledScope scope(frame); 5757 VirtualFrame::SpilledScope scope(frame);
5508 Comment cmnt(masm, "[ Store to keyed Property"); 5758 Comment cmnt(masm, "[ Store to keyed Property");
5509 Property* property = expression_->AsProperty(); 5759 Property* property = expression_->AsProperty();
5510 ASSERT(property != NULL); 5760 ASSERT(property != NULL);
(...skipping 3938 matching lines...) Expand 10 before | Expand all | Expand 10 after
9449 9699
9450 // Just jump to runtime to add the two strings. 9700 // Just jump to runtime to add the two strings.
9451 __ bind(&string_add_runtime); 9701 __ bind(&string_add_runtime);
9452 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 9702 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
9453 } 9703 }
9454 9704
9455 9705
9456 #undef __ 9706 #undef __
9457 9707
9458 } } // namespace v8::internal 9708 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/virtual-frame-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698