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 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |