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

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

Issue 362004: Remove the typeof state threaded through the code generator. It was... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 1 month 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/ia32/codegen-ia32.h ('k') | src/x64/codegen-x64.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 } 68 }
69 } 69 }
70 } 70 }
71 71
72 72
73 // ------------------------------------------------------------------------- 73 // -------------------------------------------------------------------------
74 // CodeGenState implementation. 74 // CodeGenState implementation.
75 75
76 CodeGenState::CodeGenState(CodeGenerator* owner) 76 CodeGenState::CodeGenState(CodeGenerator* owner)
77 : owner_(owner), 77 : owner_(owner),
78 typeof_state_(NOT_INSIDE_TYPEOF),
79 destination_(NULL), 78 destination_(NULL),
80 previous_(NULL) { 79 previous_(NULL) {
81 owner_->set_state(this); 80 owner_->set_state(this);
82 } 81 }
83 82
84 83
85 CodeGenState::CodeGenState(CodeGenerator* owner, 84 CodeGenState::CodeGenState(CodeGenerator* owner,
86 TypeofState typeof_state,
87 ControlDestination* destination) 85 ControlDestination* destination)
88 : owner_(owner), 86 : owner_(owner),
89 typeof_state_(typeof_state),
90 destination_(destination), 87 destination_(destination),
91 previous_(owner->state()) { 88 previous_(owner->state()) {
92 owner_->set_state(this); 89 owner_->set_state(this);
93 } 90 }
94 91
95 92
96 CodeGenState::~CodeGenState() { 93 CodeGenState::~CodeGenState() {
97 ASSERT(owner_->state() == this); 94 ASSERT(owner_->state() == this);
98 owner_->set_state(previous_); 95 owner_->set_state(previous_);
99 } 96 }
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 __ mov(tmp.reg(), ContextOperand(context, Context::FCONTEXT_INDEX)); 405 __ mov(tmp.reg(), ContextOperand(context, Context::FCONTEXT_INDEX));
409 return ContextOperand(tmp.reg(), slot->index()); 406 return ContextOperand(tmp.reg(), slot->index());
410 } 407 }
411 408
412 409
413 // Emit code to load the value of an expression to the top of the 410 // Emit code to load the value of an expression to the top of the
414 // frame. If the expression is boolean-valued it may be compiled (or 411 // frame. If the expression is boolean-valued it may be compiled (or
415 // partially compiled) into control flow to the control destination. 412 // partially compiled) into control flow to the control destination.
416 // If force_control is true, control flow is forced. 413 // If force_control is true, control flow is forced.
417 void CodeGenerator::LoadCondition(Expression* x, 414 void CodeGenerator::LoadCondition(Expression* x,
418 TypeofState typeof_state,
419 ControlDestination* dest, 415 ControlDestination* dest,
420 bool force_control) { 416 bool force_control) {
421 ASSERT(!in_spilled_code()); 417 ASSERT(!in_spilled_code());
422 int original_height = frame_->height(); 418 int original_height = frame_->height();
423 419
424 { CodeGenState new_state(this, typeof_state, dest); 420 { CodeGenState new_state(this, dest);
425 Visit(x); 421 Visit(x);
426 422
427 // If we hit a stack overflow, we may not have actually visited 423 // If we hit a stack overflow, we may not have actually visited
428 // the expression. In that case, we ensure that we have a 424 // the expression. In that case, we ensure that we have a
429 // valid-looking frame state because we will continue to generate 425 // valid-looking frame state because we will continue to generate
430 // code as we unwind the C++ stack. 426 // code as we unwind the C++ stack.
431 // 427 //
432 // It's possible to have both a stack overflow and a valid frame 428 // It's possible to have both a stack overflow and a valid frame
433 // state (eg, a subexpression overflowed, visiting it returned 429 // state (eg, a subexpression overflowed, visiting it returned
434 // with a dummied frame state, and visiting this expression 430 // with a dummied frame state, and visiting this expression
435 // returned with a normal-looking state). 431 // returned with a normal-looking state).
436 if (HasStackOverflow() && 432 if (HasStackOverflow() &&
437 !dest->is_used() && 433 !dest->is_used() &&
438 frame_->height() == original_height) { 434 frame_->height() == original_height) {
439 dest->Goto(true); 435 dest->Goto(true);
440 } 436 }
441 } 437 }
442 438
443 if (force_control && !dest->is_used()) { 439 if (force_control && !dest->is_used()) {
444 // Convert the TOS value into flow to the control destination. 440 // Convert the TOS value into flow to the control destination.
445 ToBoolean(dest); 441 ToBoolean(dest);
446 } 442 }
447 443
448 ASSERT(!(force_control && !dest->is_used())); 444 ASSERT(!(force_control && !dest->is_used()));
449 ASSERT(dest->is_used() || frame_->height() == original_height + 1); 445 ASSERT(dest->is_used() || frame_->height() == original_height + 1);
450 } 446 }
451 447
452 448
453 void CodeGenerator::LoadAndSpill(Expression* expression, 449 void CodeGenerator::LoadAndSpill(Expression* expression) {
454 TypeofState typeof_state) {
455 ASSERT(in_spilled_code()); 450 ASSERT(in_spilled_code());
456 set_in_spilled_code(false); 451 set_in_spilled_code(false);
457 Load(expression, typeof_state); 452 Load(expression);
458 frame_->SpillAll(); 453 frame_->SpillAll();
459 set_in_spilled_code(true); 454 set_in_spilled_code(true);
460 } 455 }
461 456
462 457
463 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 458 void CodeGenerator::Load(Expression* expr) {
464 #ifdef DEBUG 459 #ifdef DEBUG
465 int original_height = frame_->height(); 460 int original_height = frame_->height();
466 #endif 461 #endif
467 ASSERT(!in_spilled_code()); 462 ASSERT(!in_spilled_code());
468 JumpTarget true_target; 463 JumpTarget true_target;
469 JumpTarget false_target; 464 JumpTarget false_target;
470 ControlDestination dest(&true_target, &false_target, true); 465 ControlDestination dest(&true_target, &false_target, true);
471 LoadCondition(x, typeof_state, &dest, false); 466 LoadCondition(expr, &dest, false);
472 467
473 if (dest.false_was_fall_through()) { 468 if (dest.false_was_fall_through()) {
474 // The false target was just bound. 469 // The false target was just bound.
475 JumpTarget loaded; 470 JumpTarget loaded;
476 frame_->Push(Factory::false_value()); 471 frame_->Push(Factory::false_value());
477 // There may be dangling jumps to the true target. 472 // There may be dangling jumps to the true target.
478 if (true_target.is_linked()) { 473 if (true_target.is_linked()) {
479 loaded.Jump(); 474 loaded.Jump();
480 true_target.Bind(); 475 true_target.Bind();
481 frame_->Push(Factory::true_value()); 476 frame_->Push(Factory::true_value());
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 531
537 void CodeGenerator::LoadGlobalReceiver() { 532 void CodeGenerator::LoadGlobalReceiver() {
538 Result temp = allocator_->Allocate(); 533 Result temp = allocator_->Allocate();
539 Register reg = temp.reg(); 534 Register reg = temp.reg();
540 __ mov(reg, GlobalObject()); 535 __ mov(reg, GlobalObject());
541 __ mov(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset)); 536 __ mov(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset));
542 frame_->Push(&temp); 537 frame_->Push(&temp);
543 } 538 }
544 539
545 540
546 // TODO(1241834): Get rid of this function in favor of just using Load, now 541 void CodeGenerator::LoadTypeofExpression(Expression* expr) {
547 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global 542 // Special handling of identifiers as subexpressions of typeof.
548 // variables w/o reference errors elsewhere. 543 Variable* variable = expr->AsVariableProxy()->AsVariable();
549 void CodeGenerator::LoadTypeofExpression(Expression* x) {
550 Variable* variable = x->AsVariableProxy()->AsVariable();
551 if (variable != NULL && !variable->is_this() && variable->is_global()) { 544 if (variable != NULL && !variable->is_this() && variable->is_global()) {
552 // NOTE: This is somewhat nasty. We force the compiler to load 545 // For a global variable we build the property reference
553 // the variable as if through '<global>.<variable>' to make sure we 546 // <global>.<variable> and perform a (regular non-contextual) property
554 // do not get reference errors. 547 // load to make sure we do not get reference errors.
555 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); 548 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
556 Literal key(variable->name()); 549 Literal key(variable->name());
557 // TODO(1241834): Fetch the position from the variable instead of using 550 // TODO(1241834): Fetch the position from the variable instead of using
558 // no position. 551 // no position.
559 Property property(&global, &key, RelocInfo::kNoPosition); 552 Property property(&global, &key, RelocInfo::kNoPosition);
560 Load(&property); 553 Reference ref(this, &property);
554 ref.GetValue();
555 } else if (variable != NULL && variable->slot() != NULL) {
556 // For a variable that rewrites to a slot, we signal it is the immediate
557 // subexpression of a typeof.
558 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF);
561 } else { 559 } else {
562 Load(x, INSIDE_TYPEOF); 560 // Anything else can be handled normally.
561 Load(expr);
563 } 562 }
564 } 563 }
565 564
566 565
567 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() const { 566 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() const {
568 if (scope_->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; 567 if (scope_->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
569 ASSERT(scope_->arguments_shadow() != NULL); 568 ASSERT(scope_->arguments_shadow() != NULL);
570 // We don't want to do lazy arguments allocation for functions that 569 // We don't want to do lazy arguments allocation for functions that
571 // have heap-allocated contexts, because it interfers with the 570 // have heap-allocated contexts, because it interfers with the
572 // uninitialized const tracking in the context objects. 571 // uninitialized const tracking in the context objects.
(...skipping 1426 matching lines...) Expand 10 before | Expand all | Expand 10 after
1999 VariableProxy* arguments, 1998 VariableProxy* arguments,
2000 int position) { 1999 int position) {
2001 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); 2000 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION);
2002 ASSERT(arguments->IsArguments()); 2001 ASSERT(arguments->IsArguments());
2003 2002
2004 JumpTarget slow, done; 2003 JumpTarget slow, done;
2005 2004
2006 // Load the apply function onto the stack. This will usually 2005 // Load the apply function onto the stack. This will usually
2007 // give us a megamorphic load site. Not super, but it works. 2006 // give us a megamorphic load site. Not super, but it works.
2008 Reference ref(this, apply); 2007 Reference ref(this, apply);
2009 ref.GetValue(NOT_INSIDE_TYPEOF); 2008 ref.GetValue();
2010 ASSERT(ref.type() == Reference::NAMED); 2009 ASSERT(ref.type() == Reference::NAMED);
2011 2010
2012 // Load the receiver and the existing arguments object onto the 2011 // Load the receiver and the existing arguments object onto the
2013 // expression stack. Avoid allocating the arguments object here. 2012 // expression stack. Avoid allocating the arguments object here.
2014 Load(receiver); 2013 Load(receiver);
2015 LoadFromSlot(scope_->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); 2014 LoadFromSlot(scope_->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
2016 2015
2017 // Emit the source position information after having loaded the 2016 // Emit the source position information after having loaded the
2018 // receiver and the arguments. 2017 // receiver and the arguments.
2019 CodeForSourcePosition(position); 2018 CodeForSourcePosition(position);
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
2338 // are present or not. 2337 // are present or not.
2339 bool has_then_stm = node->HasThenStatement(); 2338 bool has_then_stm = node->HasThenStatement();
2340 bool has_else_stm = node->HasElseStatement(); 2339 bool has_else_stm = node->HasElseStatement();
2341 2340
2342 CodeForStatementPosition(node); 2341 CodeForStatementPosition(node);
2343 JumpTarget exit; 2342 JumpTarget exit;
2344 if (has_then_stm && has_else_stm) { 2343 if (has_then_stm && has_else_stm) {
2345 JumpTarget then; 2344 JumpTarget then;
2346 JumpTarget else_; 2345 JumpTarget else_;
2347 ControlDestination dest(&then, &else_, true); 2346 ControlDestination dest(&then, &else_, true);
2348 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 2347 LoadCondition(node->condition(), &dest, true);
2349 2348
2350 if (dest.false_was_fall_through()) { 2349 if (dest.false_was_fall_through()) {
2351 // The else target was bound, so we compile the else part first. 2350 // The else target was bound, so we compile the else part first.
2352 Visit(node->else_statement()); 2351 Visit(node->else_statement());
2353 2352
2354 // We may have dangling jumps to the then part. 2353 // We may have dangling jumps to the then part.
2355 if (then.is_linked()) { 2354 if (then.is_linked()) {
2356 if (has_valid_frame()) exit.Jump(); 2355 if (has_valid_frame()) exit.Jump();
2357 then.Bind(); 2356 then.Bind();
2358 Visit(node->then_statement()); 2357 Visit(node->then_statement());
2359 } 2358 }
2360 } else { 2359 } else {
2361 // The then target was bound, so we compile the then part first. 2360 // The then target was bound, so we compile the then part first.
2362 Visit(node->then_statement()); 2361 Visit(node->then_statement());
2363 2362
2364 if (else_.is_linked()) { 2363 if (else_.is_linked()) {
2365 if (has_valid_frame()) exit.Jump(); 2364 if (has_valid_frame()) exit.Jump();
2366 else_.Bind(); 2365 else_.Bind();
2367 Visit(node->else_statement()); 2366 Visit(node->else_statement());
2368 } 2367 }
2369 } 2368 }
2370 2369
2371 } else if (has_then_stm) { 2370 } else if (has_then_stm) {
2372 ASSERT(!has_else_stm); 2371 ASSERT(!has_else_stm);
2373 JumpTarget then; 2372 JumpTarget then;
2374 ControlDestination dest(&then, &exit, true); 2373 ControlDestination dest(&then, &exit, true);
2375 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 2374 LoadCondition(node->condition(), &dest, true);
2376 2375
2377 if (dest.false_was_fall_through()) { 2376 if (dest.false_was_fall_through()) {
2378 // The exit label was bound. We may have dangling jumps to the 2377 // The exit label was bound. We may have dangling jumps to the
2379 // then part. 2378 // then part.
2380 if (then.is_linked()) { 2379 if (then.is_linked()) {
2381 exit.Unuse(); 2380 exit.Unuse();
2382 exit.Jump(); 2381 exit.Jump();
2383 then.Bind(); 2382 then.Bind();
2384 Visit(node->then_statement()); 2383 Visit(node->then_statement());
2385 } 2384 }
2386 } else { 2385 } else {
2387 // The then label was bound. 2386 // The then label was bound.
2388 Visit(node->then_statement()); 2387 Visit(node->then_statement());
2389 } 2388 }
2390 2389
2391 } else if (has_else_stm) { 2390 } else if (has_else_stm) {
2392 ASSERT(!has_then_stm); 2391 ASSERT(!has_then_stm);
2393 JumpTarget else_; 2392 JumpTarget else_;
2394 ControlDestination dest(&exit, &else_, false); 2393 ControlDestination dest(&exit, &else_, false);
2395 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 2394 LoadCondition(node->condition(), &dest, true);
2396 2395
2397 if (dest.true_was_fall_through()) { 2396 if (dest.true_was_fall_through()) {
2398 // The exit label was bound. We may have dangling jumps to the 2397 // The exit label was bound. We may have dangling jumps to the
2399 // else part. 2398 // else part.
2400 if (else_.is_linked()) { 2399 if (else_.is_linked()) {
2401 exit.Unuse(); 2400 exit.Unuse();
2402 exit.Jump(); 2401 exit.Jump();
2403 else_.Bind(); 2402 else_.Bind();
2404 Visit(node->else_statement()); 2403 Visit(node->else_statement());
2405 } 2404 }
2406 } else { 2405 } else {
2407 // The else label was bound. 2406 // The else label was bound.
2408 Visit(node->else_statement()); 2407 Visit(node->else_statement());
2409 } 2408 }
2410 2409
2411 } else { 2410 } else {
2412 ASSERT(!has_then_stm && !has_else_stm); 2411 ASSERT(!has_then_stm && !has_else_stm);
2413 // We only care about the condition's side effects (not its value 2412 // We only care about the condition's side effects (not its value
2414 // or control flow effect). LoadCondition is called without 2413 // or control flow effect). LoadCondition is called without
2415 // forcing control flow. 2414 // forcing control flow.
2416 ControlDestination dest(&exit, &exit, true); 2415 ControlDestination dest(&exit, &exit, true);
2417 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, false); 2416 LoadCondition(node->condition(), &dest, false);
2418 if (!dest.is_used()) { 2417 if (!dest.is_used()) {
2419 // We got a value on the frame rather than (or in addition to) 2418 // We got a value on the frame rather than (or in addition to)
2420 // control flow. 2419 // control flow.
2421 frame_->Drop(); 2420 frame_->Drop();
2422 } 2421 }
2423 } 2422 }
2424 2423
2425 if (exit.is_linked()) { 2424 if (exit.is_linked()) {
2426 exit.Bind(); 2425 exit.Bind();
2427 } 2426 }
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
2708 } 2707 }
2709 break; 2708 break;
2710 case DONT_KNOW: 2709 case DONT_KNOW:
2711 // We have to compile the test expression if it can be reached by 2710 // We have to compile the test expression if it can be reached by
2712 // control flow falling out of the body or via continue. 2711 // control flow falling out of the body or via continue.
2713 if (node->continue_target()->is_linked()) { 2712 if (node->continue_target()->is_linked()) {
2714 node->continue_target()->Bind(); 2713 node->continue_target()->Bind();
2715 } 2714 }
2716 if (has_valid_frame()) { 2715 if (has_valid_frame()) {
2717 ControlDestination dest(&body, node->break_target(), false); 2716 ControlDestination dest(&body, node->break_target(), false);
2718 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2717 LoadCondition(node->cond(), &dest, true);
2719 } 2718 }
2720 if (node->break_target()->is_linked()) { 2719 if (node->break_target()->is_linked()) {
2721 node->break_target()->Bind(); 2720 node->break_target()->Bind();
2722 } 2721 }
2723 break; 2722 break;
2724 } 2723 }
2725 2724
2726 DecrementLoopNesting(); 2725 DecrementLoopNesting();
2727 } 2726 }
2728 2727
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2763 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 2762 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2764 } else { 2763 } else {
2765 // Label the test at the top as the continue target. The body 2764 // Label the test at the top as the continue target. The body
2766 // is a forward-only target. 2765 // is a forward-only target.
2767 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); 2766 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2768 node->continue_target()->Bind(); 2767 node->continue_target()->Bind();
2769 } 2768 }
2770 // Compile the test with the body as the true target and preferred 2769 // Compile the test with the body as the true target and preferred
2771 // fall-through and with the break target as the false target. 2770 // fall-through and with the break target as the false target.
2772 ControlDestination dest(&body, node->break_target(), true); 2771 ControlDestination dest(&body, node->break_target(), true);
2773 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2772 LoadCondition(node->cond(), &dest, true);
2774 2773
2775 if (dest.false_was_fall_through()) { 2774 if (dest.false_was_fall_through()) {
2776 // If we got the break target as fall-through, the test may have 2775 // If we got the break target as fall-through, the test may have
2777 // been unconditionally false (if there are no jumps to the 2776 // been unconditionally false (if there are no jumps to the
2778 // body). 2777 // body).
2779 if (!body.is_linked()) { 2778 if (!body.is_linked()) {
2780 DecrementLoopNesting(); 2779 DecrementLoopNesting();
2781 return; 2780 return;
2782 } 2781 }
2783 2782
(...skipping 26 matching lines...) Expand all
2810 if (test_at_bottom) { 2809 if (test_at_bottom) {
2811 // If we have chosen to recompile the test at the bottom, then 2810 // If we have chosen to recompile the test at the bottom, then
2812 // it is the continue target. 2811 // it is the continue target.
2813 if (node->continue_target()->is_linked()) { 2812 if (node->continue_target()->is_linked()) {
2814 node->continue_target()->Bind(); 2813 node->continue_target()->Bind();
2815 } 2814 }
2816 if (has_valid_frame()) { 2815 if (has_valid_frame()) {
2817 // The break target is the fall-through (body is a backward 2816 // The break target is the fall-through (body is a backward
2818 // jump from here and thus an invalid fall-through). 2817 // jump from here and thus an invalid fall-through).
2819 ControlDestination dest(&body, node->break_target(), false); 2818 ControlDestination dest(&body, node->break_target(), false);
2820 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2819 LoadCondition(node->cond(), &dest, true);
2821 } 2820 }
2822 } else { 2821 } else {
2823 // If we have chosen not to recompile the test at the bottom, 2822 // If we have chosen not to recompile the test at the bottom,
2824 // jump back to the one at the top. 2823 // jump back to the one at the top.
2825 if (has_valid_frame()) { 2824 if (has_valid_frame()) {
2826 node->continue_target()->Jump(); 2825 node->continue_target()->Jump();
2827 } 2826 }
2828 } 2827 }
2829 break; 2828 break;
2830 case ALWAYS_FALSE: 2829 case ALWAYS_FALSE:
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
2901 node->continue_target()->Bind(); 2900 node->continue_target()->Bind();
2902 } else { 2901 } else {
2903 // We are not recompiling the test at the bottom and there is an 2902 // We are not recompiling the test at the bottom and there is an
2904 // update expression. 2903 // update expression.
2905 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 2904 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2906 loop.Bind(); 2905 loop.Bind();
2907 } 2906 }
2908 // Compile the test with the body as the true target and preferred 2907 // Compile the test with the body as the true target and preferred
2909 // fall-through and with the break target as the false target. 2908 // fall-through and with the break target as the false target.
2910 ControlDestination dest(&body, node->break_target(), true); 2909 ControlDestination dest(&body, node->break_target(), true);
2911 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2910 LoadCondition(node->cond(), &dest, true);
2912 2911
2913 if (dest.false_was_fall_through()) { 2912 if (dest.false_was_fall_through()) {
2914 // If we got the break target as fall-through, the test may have 2913 // If we got the break target as fall-through, the test may have
2915 // been unconditionally false (if there are no jumps to the 2914 // been unconditionally false (if there are no jumps to the
2916 // body). 2915 // body).
2917 if (!body.is_linked()) { 2916 if (!body.is_linked()) {
2918 DecrementLoopNesting(); 2917 DecrementLoopNesting();
2919 return; 2918 return;
2920 } 2919 }
2921 2920
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2971 // was no update expression. 2970 // was no update expression.
2972 node->continue_target()->Bind(); 2971 node->continue_target()->Bind();
2973 } 2972 }
2974 // Control can reach the test at the bottom by falling out of 2973 // Control can reach the test at the bottom by falling out of
2975 // the body, by a continue in the body, or from the update 2974 // the body, by a continue in the body, or from the update
2976 // expression. 2975 // expression.
2977 if (has_valid_frame()) { 2976 if (has_valid_frame()) {
2978 // The break target is the fall-through (body is a backward 2977 // The break target is the fall-through (body is a backward
2979 // jump from here). 2978 // jump from here).
2980 ControlDestination dest(&body, node->break_target(), false); 2979 ControlDestination dest(&body, node->break_target(), false);
2981 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2980 LoadCondition(node->cond(), &dest, true);
2982 } 2981 }
2983 } else { 2982 } else {
2984 // Otherwise, jump back to the test at the top. 2983 // Otherwise, jump back to the test at the top.
2985 if (has_valid_frame()) { 2984 if (has_valid_frame()) {
2986 if (node->next() == NULL) { 2985 if (node->next() == NULL) {
2987 node->continue_target()->Jump(); 2986 node->continue_target()->Jump();
2988 } else { 2987 } else {
2989 loop.Jump(); 2988 loop.Jump();
2990 } 2989 }
2991 } 2990 }
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
3566 InstantiateBoilerplate(node->boilerplate()); 3565 InstantiateBoilerplate(node->boilerplate());
3567 } 3566 }
3568 3567
3569 3568
3570 void CodeGenerator::VisitConditional(Conditional* node) { 3569 void CodeGenerator::VisitConditional(Conditional* node) {
3571 Comment cmnt(masm_, "[ Conditional"); 3570 Comment cmnt(masm_, "[ Conditional");
3572 JumpTarget then; 3571 JumpTarget then;
3573 JumpTarget else_; 3572 JumpTarget else_;
3574 JumpTarget exit; 3573 JumpTarget exit;
3575 ControlDestination dest(&then, &else_, true); 3574 ControlDestination dest(&then, &else_, true);
3576 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 3575 LoadCondition(node->condition(), &dest, true);
3577 3576
3578 if (dest.false_was_fall_through()) { 3577 if (dest.false_was_fall_through()) {
3579 // The else target was bound, so we compile the else part first. 3578 // The else target was bound, so we compile the else part first.
3580 Load(node->else_expression(), typeof_state()); 3579 Load(node->else_expression());
3581 3580
3582 if (then.is_linked()) { 3581 if (then.is_linked()) {
3583 exit.Jump(); 3582 exit.Jump();
3584 then.Bind(); 3583 then.Bind();
3585 Load(node->then_expression(), typeof_state()); 3584 Load(node->then_expression());
3586 } 3585 }
3587 } else { 3586 } else {
3588 // The then target was bound, so we compile the then part first. 3587 // The then target was bound, so we compile the then part first.
3589 Load(node->then_expression(), typeof_state()); 3588 Load(node->then_expression());
3590 3589
3591 if (else_.is_linked()) { 3590 if (else_.is_linked()) {
3592 exit.Jump(); 3591 exit.Jump();
3593 else_.Bind(); 3592 else_.Bind();
3594 Load(node->else_expression(), typeof_state()); 3593 Load(node->else_expression());
3595 } 3594 }
3596 } 3595 }
3597 3596
3598 exit.Bind(); 3597 exit.Bind();
3599 } 3598 }
3600 3599
3601 3600
3602 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 3601 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
3603 if (slot->type() == Slot::LOOKUP) { 3602 if (slot->type() == Slot::LOOKUP) {
3604 ASSERT(slot->var()->is_dynamic()); 3603 ASSERT(slot->var()->is_dynamic());
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
3906 // scope. 3905 // scope.
3907 } 3906 }
3908 3907
3909 exit.Bind(); 3908 exit.Bind();
3910 } 3909 }
3911 } 3910 }
3912 3911
3913 3912
3914 void CodeGenerator::VisitSlot(Slot* node) { 3913 void CodeGenerator::VisitSlot(Slot* node) {
3915 Comment cmnt(masm_, "[ Slot"); 3914 Comment cmnt(masm_, "[ Slot");
3916 LoadFromSlotCheckForArguments(node, typeof_state()); 3915 LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF);
3917 } 3916 }
3918 3917
3919 3918
3920 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 3919 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
3921 Comment cmnt(masm_, "[ VariableProxy"); 3920 Comment cmnt(masm_, "[ VariableProxy");
3922 Variable* var = node->var(); 3921 Variable* var = node->var();
3923 Expression* expr = var->rewrite(); 3922 Expression* expr = var->rewrite();
3924 if (expr != NULL) { 3923 if (expr != NULL) {
3925 Visit(expr); 3924 Visit(expr);
3926 } else { 3925 } else {
3927 ASSERT(var->is_global()); 3926 ASSERT(var->is_global());
3928 Reference ref(this, node); 3927 Reference ref(this, node);
3929 ref.GetValue(typeof_state()); 3928 ref.GetValue();
3930 } 3929 }
3931 } 3930 }
3932 3931
3933 3932
3934 void CodeGenerator::VisitLiteral(Literal* node) { 3933 void CodeGenerator::VisitLiteral(Literal* node) {
3935 Comment cmnt(masm_, "[ Literal"); 3934 Comment cmnt(masm_, "[ Literal");
3936 frame_->Push(node->handle()); 3935 frame_->Push(node->handle());
3937 } 3936 }
3938 3937
3939 3938
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
4326 bool overwrite_value = 4325 bool overwrite_value =
4327 (node->value()->AsBinaryOperation() != NULL && 4326 (node->value()->AsBinaryOperation() != NULL &&
4328 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 4327 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
4329 Variable* right_var = node->value()->AsVariableProxy()->AsVariable(); 4328 Variable* right_var = node->value()->AsVariableProxy()->AsVariable();
4330 // There are two cases where the target is not read in the right hand 4329 // There are two cases where the target is not read in the right hand
4331 // side, that are easy to test for: the right hand side is a literal, 4330 // side, that are easy to test for: the right hand side is a literal,
4332 // or the right hand side is a different variable. TakeValue invalidates 4331 // or the right hand side is a different variable. TakeValue invalidates
4333 // the target, with an implicit promise that it will be written to again 4332 // the target, with an implicit promise that it will be written to again
4334 // before it is read. 4333 // before it is read.
4335 if (literal != NULL || (right_var != NULL && right_var != var)) { 4334 if (literal != NULL || (right_var != NULL && right_var != var)) {
4336 target.TakeValue(NOT_INSIDE_TYPEOF); 4335 target.TakeValue();
4337 } else { 4336 } else {
4338 target.GetValue(NOT_INSIDE_TYPEOF); 4337 target.GetValue();
4339 } 4338 }
4340 Load(node->value()); 4339 Load(node->value());
4341 GenericBinaryOperation(node->binary_op(), 4340 GenericBinaryOperation(node->binary_op(),
4342 node->type(), 4341 node->type(),
4343 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); 4342 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
4344 } 4343 }
4345 4344
4346 if (var != NULL && 4345 if (var != NULL &&
4347 var->mode() == Variable::CONST && 4346 var->mode() == Variable::CONST &&
4348 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { 4347 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
(...skipping 27 matching lines...) Expand all
4376 Comment cmnt(masm_, "[ Throw"); 4375 Comment cmnt(masm_, "[ Throw");
4377 Load(node->exception()); 4376 Load(node->exception());
4378 Result result = frame_->CallRuntime(Runtime::kThrow, 1); 4377 Result result = frame_->CallRuntime(Runtime::kThrow, 1);
4379 frame_->Push(&result); 4378 frame_->Push(&result);
4380 } 4379 }
4381 4380
4382 4381
4383 void CodeGenerator::VisitProperty(Property* node) { 4382 void CodeGenerator::VisitProperty(Property* node) {
4384 Comment cmnt(masm_, "[ Property"); 4383 Comment cmnt(masm_, "[ Property");
4385 Reference property(this, node); 4384 Reference property(this, node);
4386 property.GetValue(typeof_state()); 4385 property.GetValue();
4387 } 4386 }
4388 4387
4389 4388
4390 void CodeGenerator::VisitCall(Call* node) { 4389 void CodeGenerator::VisitCall(Call* node) {
4391 Comment cmnt(masm_, "[ Call"); 4390 Comment cmnt(masm_, "[ Call");
4392 4391
4393 Expression* function = node->expression(); 4392 Expression* function = node->expression();
4394 ZoneList<Expression*>* args = node->arguments(); 4393 ZoneList<Expression*>* args = node->arguments();
4395 4394
4396 // Check if the function is a variable or a property. 4395 // Check if the function is a variable or a property.
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
4561 frame_->SetElementAt(0, &result); 4560 frame_->SetElementAt(0, &result);
4562 } 4561 }
4563 4562
4564 } else { 4563 } else {
4565 // ------------------------------------------- 4564 // -------------------------------------------
4566 // JavaScript example: 'array[index](1, 2, 3)' 4565 // JavaScript example: 'array[index](1, 2, 3)'
4567 // ------------------------------------------- 4566 // -------------------------------------------
4568 4567
4569 // Load the function to call from the property through a reference. 4568 // Load the function to call from the property through a reference.
4570 Reference ref(this, property); 4569 Reference ref(this, property);
4571 ref.GetValue(NOT_INSIDE_TYPEOF); 4570 ref.GetValue();
4572 4571
4573 // Pass receiver to called function. 4572 // Pass receiver to called function.
4574 if (property->is_synthetic()) { 4573 if (property->is_synthetic()) {
4575 // Use global object as receiver. 4574 // Use global object as receiver.
4576 LoadGlobalReceiver(); 4575 LoadGlobalReceiver();
4577 } else { 4576 } else {
4578 // The reference's size is non-negative. 4577 // The reference's size is non-negative.
4579 frame_->PushElementAt(ref.size()); 4578 frame_->PushElementAt(ref.size());
4580 } 4579 }
4581 4580
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
5196 frame_->SetElementAt(0, &answer); 5195 frame_->SetElementAt(0, &answer);
5197 } else { 5196 } else {
5198 // Call the C runtime function. 5197 // Call the C runtime function.
5199 Result answer = frame_->CallRuntime(function, arg_count); 5198 Result answer = frame_->CallRuntime(function, arg_count);
5200 frame_->Push(&answer); 5199 frame_->Push(&answer);
5201 } 5200 }
5202 } 5201 }
5203 5202
5204 5203
5205 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 5204 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
5206 // Note that because of NOT and an optimization in comparison of a typeof
5207 // expression to a literal string, this function can fail to leave a value
5208 // on top of the frame or in the cc register.
5209 Comment cmnt(masm_, "[ UnaryOperation"); 5205 Comment cmnt(masm_, "[ UnaryOperation");
5210 5206
5211 Token::Value op = node->op(); 5207 Token::Value op = node->op();
5212 5208
5213 if (op == Token::NOT) { 5209 if (op == Token::NOT) {
5214 // Swap the true and false targets but keep the same actual label 5210 // Swap the true and false targets but keep the same actual label
5215 // as the fall through. 5211 // as the fall through.
5216 destination()->Invert(); 5212 destination()->Invert();
5217 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, destination(), true); 5213 LoadCondition(node->expression(), destination(), true);
5218 // Swap the labels back. 5214 // Swap the labels back.
5219 destination()->Invert(); 5215 destination()->Invert();
5220 5216
5221 } else if (op == Token::DELETE) { 5217 } else if (op == Token::DELETE) {
5222 Property* property = node->expression()->AsProperty(); 5218 Property* property = node->expression()->AsProperty();
5223 if (property != NULL) { 5219 if (property != NULL) {
5224 Load(property->obj()); 5220 Load(property->obj());
5225 Load(property->key()); 5221 Load(property->key());
5226 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); 5222 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
5227 frame_->Push(&answer); 5223 frame_->Push(&answer);
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
5457 // value will be in the frame to be spilled. 5453 // value will be in the frame to be spilled.
5458 if (is_postfix) frame_->Push(Smi::FromInt(0)); 5454 if (is_postfix) frame_->Push(Smi::FromInt(0));
5459 5455
5460 { Reference target(this, node->expression()); 5456 { Reference target(this, node->expression());
5461 if (target.is_illegal()) { 5457 if (target.is_illegal()) {
5462 // Spoof the virtual frame to have the expected height (one higher 5458 // Spoof the virtual frame to have the expected height (one higher
5463 // than on entry). 5459 // than on entry).
5464 if (!is_postfix) frame_->Push(Smi::FromInt(0)); 5460 if (!is_postfix) frame_->Push(Smi::FromInt(0));
5465 return; 5461 return;
5466 } 5462 }
5467 target.TakeValue(NOT_INSIDE_TYPEOF); 5463 target.TakeValue();
5468 5464
5469 Result new_value = frame_->Pop(); 5465 Result new_value = frame_->Pop();
5470 new_value.ToRegister(); 5466 new_value.ToRegister();
5471 5467
5472 Result old_value; // Only allocated in the postfix case. 5468 Result old_value; // Only allocated in the postfix case.
5473 if (is_postfix) { 5469 if (is_postfix) {
5474 // Allocate a temporary to preserve the old value. 5470 // Allocate a temporary to preserve the old value.
5475 old_value = allocator_->Allocate(); 5471 old_value = allocator_->Allocate();
5476 ASSERT(old_value.is_valid()); 5472 ASSERT(old_value.is_valid());
5477 __ mov(old_value.reg(), new_value.reg()); 5473 __ mov(old_value.reg(), new_value.reg());
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
5535 // Non-constant: update the reference. 5531 // Non-constant: update the reference.
5536 if (!is_const) target.SetValue(NOT_CONST_INIT); 5532 if (!is_const) target.SetValue(NOT_CONST_INIT);
5537 } 5533 }
5538 5534
5539 // Postfix: drop the new value and use the old. 5535 // Postfix: drop the new value and use the old.
5540 if (is_postfix) frame_->Drop(); 5536 if (is_postfix) frame_->Drop();
5541 } 5537 }
5542 5538
5543 5539
5544 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 5540 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
5545 // Note that due to an optimization in comparison operations (typeof
5546 // compared to a string literal), we can evaluate a binary expression such
5547 // as AND or OR and not leave a value on the frame or in the cc register.
5548 Comment cmnt(masm_, "[ BinaryOperation"); 5541 Comment cmnt(masm_, "[ BinaryOperation");
5549 Token::Value op = node->op(); 5542 Token::Value op = node->op();
5550 5543
5551 // According to ECMA-262 section 11.11, page 58, the binary logical 5544 // According to ECMA-262 section 11.11, page 58, the binary logical
5552 // operators must yield the result of one of the two expressions 5545 // operators must yield the result of one of the two expressions
5553 // before any ToBoolean() conversions. This means that the value 5546 // before any ToBoolean() conversions. This means that the value
5554 // produced by a && or || operator is not necessarily a boolean. 5547 // produced by a && or || operator is not necessarily a boolean.
5555 5548
5556 // NOTE: If the left hand side produces a materialized value (not 5549 // NOTE: If the left hand side produces a materialized value (not
5557 // control flow), we force the right hand side to do the same. This 5550 // control flow), we force the right hand side to do the same. This
5558 // is necessary because we assume that if we get control flow on the 5551 // is necessary because we assume that if we get control flow on the
5559 // last path out of an expression we got it on all paths. 5552 // last path out of an expression we got it on all paths.
5560 if (op == Token::AND) { 5553 if (op == Token::AND) {
5561 JumpTarget is_true; 5554 JumpTarget is_true;
5562 ControlDestination dest(&is_true, destination()->false_target(), true); 5555 ControlDestination dest(&is_true, destination()->false_target(), true);
5563 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false); 5556 LoadCondition(node->left(), &dest, false);
5564 5557
5565 if (dest.false_was_fall_through()) { 5558 if (dest.false_was_fall_through()) {
5566 // The current false target was used as the fall-through. If 5559 // The current false target was used as the fall-through. If
5567 // there are no dangling jumps to is_true then the left 5560 // there are no dangling jumps to is_true then the left
5568 // subexpression was unconditionally false. Otherwise we have 5561 // subexpression was unconditionally false. Otherwise we have
5569 // paths where we do have to evaluate the right subexpression. 5562 // paths where we do have to evaluate the right subexpression.
5570 if (is_true.is_linked()) { 5563 if (is_true.is_linked()) {
5571 // We need to compile the right subexpression. If the jump to 5564 // We need to compile the right subexpression. If the jump to
5572 // the current false target was a forward jump then we have a 5565 // the current false target was a forward jump then we have a
5573 // valid frame, we have just bound the false target, and we 5566 // valid frame, we have just bound the false target, and we
5574 // have to jump around the code for the right subexpression. 5567 // have to jump around the code for the right subexpression.
5575 if (has_valid_frame()) { 5568 if (has_valid_frame()) {
5576 destination()->false_target()->Unuse(); 5569 destination()->false_target()->Unuse();
5577 destination()->false_target()->Jump(); 5570 destination()->false_target()->Jump();
5578 } 5571 }
5579 is_true.Bind(); 5572 is_true.Bind();
5580 // The left subexpression compiled to control flow, so the 5573 // The left subexpression compiled to control flow, so the
5581 // right one is free to do so as well. 5574 // right one is free to do so as well.
5582 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); 5575 LoadCondition(node->right(), destination(), false);
5583 } else { 5576 } else {
5584 // We have actually just jumped to or bound the current false 5577 // We have actually just jumped to or bound the current false
5585 // target but the current control destination is not marked as 5578 // target but the current control destination is not marked as
5586 // used. 5579 // used.
5587 destination()->Use(false); 5580 destination()->Use(false);
5588 } 5581 }
5589 5582
5590 } else if (dest.is_used()) { 5583 } else if (dest.is_used()) {
5591 // The left subexpression compiled to control flow (and is_true 5584 // The left subexpression compiled to control flow (and is_true
5592 // was just bound), so the right is free to do so as well. 5585 // was just bound), so the right is free to do so as well.
5593 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); 5586 LoadCondition(node->right(), destination(), false);
5594 5587
5595 } else { 5588 } else {
5596 // We have a materialized value on the frame, so we exit with 5589 // We have a materialized value on the frame, so we exit with
5597 // one on all paths. There are possibly also jumps to is_true 5590 // one on all paths. There are possibly also jumps to is_true
5598 // from nested subexpressions. 5591 // from nested subexpressions.
5599 JumpTarget pop_and_continue; 5592 JumpTarget pop_and_continue;
5600 JumpTarget exit; 5593 JumpTarget exit;
5601 5594
5602 // Avoid popping the result if it converts to 'false' using the 5595 // Avoid popping the result if it converts to 'false' using the
5603 // standard ToBoolean() conversion as described in ECMA-262, 5596 // standard ToBoolean() conversion as described in ECMA-262,
(...skipping 12 matching lines...) Expand all
5616 is_true.Bind(); 5609 is_true.Bind();
5617 Load(node->right()); 5610 Load(node->right());
5618 5611
5619 // Exit (always with a materialized value). 5612 // Exit (always with a materialized value).
5620 exit.Bind(); 5613 exit.Bind();
5621 } 5614 }
5622 5615
5623 } else if (op == Token::OR) { 5616 } else if (op == Token::OR) {
5624 JumpTarget is_false; 5617 JumpTarget is_false;
5625 ControlDestination dest(destination()->true_target(), &is_false, false); 5618 ControlDestination dest(destination()->true_target(), &is_false, false);
5626 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false); 5619 LoadCondition(node->left(), &dest, false);
5627 5620
5628 if (dest.true_was_fall_through()) { 5621 if (dest.true_was_fall_through()) {
5629 // The current true target was used as the fall-through. If 5622 // The current true target was used as the fall-through. If
5630 // there are no dangling jumps to is_false then the left 5623 // there are no dangling jumps to is_false then the left
5631 // subexpression was unconditionally true. Otherwise we have 5624 // subexpression was unconditionally true. Otherwise we have
5632 // paths where we do have to evaluate the right subexpression. 5625 // paths where we do have to evaluate the right subexpression.
5633 if (is_false.is_linked()) { 5626 if (is_false.is_linked()) {
5634 // We need to compile the right subexpression. If the jump to 5627 // We need to compile the right subexpression. If the jump to
5635 // the current true target was a forward jump then we have a 5628 // the current true target was a forward jump then we have a
5636 // valid frame, we have just bound the true target, and we 5629 // valid frame, we have just bound the true target, and we
5637 // have to jump around the code for the right subexpression. 5630 // have to jump around the code for the right subexpression.
5638 if (has_valid_frame()) { 5631 if (has_valid_frame()) {
5639 destination()->true_target()->Unuse(); 5632 destination()->true_target()->Unuse();
5640 destination()->true_target()->Jump(); 5633 destination()->true_target()->Jump();
5641 } 5634 }
5642 is_false.Bind(); 5635 is_false.Bind();
5643 // The left subexpression compiled to control flow, so the 5636 // The left subexpression compiled to control flow, so the
5644 // right one is free to do so as well. 5637 // right one is free to do so as well.
5645 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); 5638 LoadCondition(node->right(), destination(), false);
5646 } else { 5639 } else {
5647 // We have just jumped to or bound the current true target but 5640 // We have just jumped to or bound the current true target but
5648 // the current control destination is not marked as used. 5641 // the current control destination is not marked as used.
5649 destination()->Use(true); 5642 destination()->Use(true);
5650 } 5643 }
5651 5644
5652 } else if (dest.is_used()) { 5645 } else if (dest.is_used()) {
5653 // The left subexpression compiled to control flow (and is_false 5646 // The left subexpression compiled to control flow (and is_false
5654 // was just bound), so the right is free to do so as well. 5647 // was just bound), so the right is free to do so as well.
5655 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); 5648 LoadCondition(node->right(), destination(), false);
5656 5649
5657 } else { 5650 } else {
5658 // We have a materialized value on the frame, so we exit with 5651 // We have a materialized value on the frame, so we exit with
5659 // one on all paths. There are possibly also jumps to is_false 5652 // one on all paths. There are possibly also jumps to is_false
5660 // from nested subexpressions. 5653 // from nested subexpressions.
5661 JumpTarget pop_and_continue; 5654 JumpTarget pop_and_continue;
5662 JumpTarget exit; 5655 JumpTarget exit;
5663 5656
5664 // Avoid popping the result if it converts to 'true' using the 5657 // Avoid popping the result if it converts to 'true' using the
5665 // standard ToBoolean() conversion as described in ECMA-262, 5658 // standard ToBoolean() conversion as described in ECMA-262,
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
6038 ASSERT(proxy->AsVariable()->is_global()); 6031 ASSERT(proxy->AsVariable()->is_global());
6039 return proxy->name(); 6032 return proxy->name();
6040 } else { 6033 } else {
6041 Literal* raw_name = property->key()->AsLiteral(); 6034 Literal* raw_name = property->key()->AsLiteral();
6042 ASSERT(raw_name != NULL); 6035 ASSERT(raw_name != NULL);
6043 return Handle<String>(String::cast(*raw_name->handle())); 6036 return Handle<String>(String::cast(*raw_name->handle()));
6044 } 6037 }
6045 } 6038 }
6046 6039
6047 6040
6048 void Reference::GetValue(TypeofState typeof_state) { 6041 void Reference::GetValue() {
6049 ASSERT(!cgen_->in_spilled_code()); 6042 ASSERT(!cgen_->in_spilled_code());
6050 ASSERT(cgen_->HasValidEntryRegisters()); 6043 ASSERT(cgen_->HasValidEntryRegisters());
6051 ASSERT(!is_illegal()); 6044 ASSERT(!is_illegal());
6052 MacroAssembler* masm = cgen_->masm(); 6045 MacroAssembler* masm = cgen_->masm();
6053 6046
6054 // Record the source position for the property load. 6047 // Record the source position for the property load.
6055 Property* property = expression_->AsProperty(); 6048 Property* property = expression_->AsProperty();
6056 if (property != NULL) { 6049 if (property != NULL) {
6057 cgen_->CodeForSourcePosition(property->position()); 6050 cgen_->CodeForSourcePosition(property->position());
6058 } 6051 }
6059 6052
6060 switch (type_) { 6053 switch (type_) {
6061 case SLOT: { 6054 case SLOT: {
6062 Comment cmnt(masm, "[ Load from Slot"); 6055 Comment cmnt(masm, "[ Load from Slot");
6063 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 6056 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
6064 ASSERT(slot != NULL); 6057 ASSERT(slot != NULL);
6065 cgen_->LoadFromSlotCheckForArguments(slot, typeof_state); 6058 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
6066 break; 6059 break;
6067 } 6060 }
6068 6061
6069 case NAMED: { 6062 case NAMED: {
6070 // TODO(1241834): Make sure that it is safe to ignore the
6071 // distinction between expressions in a typeof and not in a
6072 // typeof. If there is a chance that reference errors can be
6073 // thrown below, we must distinguish between the two kinds of
6074 // loads (typeof expression loads must not throw a reference
6075 // error).
6076 Variable* var = expression_->AsVariableProxy()->AsVariable(); 6063 Variable* var = expression_->AsVariableProxy()->AsVariable();
6077 bool is_global = var != NULL; 6064 bool is_global = var != NULL;
6078 ASSERT(!is_global || var->is_global()); 6065 ASSERT(!is_global || var->is_global());
6079 6066
6080 // Do not inline the inobject property case for loads from the global 6067 // Do not inline the inobject property case for loads from the global
6081 // object. Also do not inline for unoptimized code. This saves time 6068 // object. Also do not inline for unoptimized code. This saves time
6082 // in the code generator. Unoptimized code is toplevel code or code 6069 // in the code generator. Unoptimized code is toplevel code or code
6083 // that is not in a loop. 6070 // that is not in a loop.
6084 if (is_global || 6071 if (is_global ||
6085 cgen_->scope()->is_global_scope() || 6072 cgen_->scope()->is_global_scope() ||
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
6135 6122
6136 __ IncrementCounter(&Counters::named_load_inline, 1); 6123 __ IncrementCounter(&Counters::named_load_inline, 1);
6137 deferred->BindExit(); 6124 deferred->BindExit();
6138 cgen_->frame()->Push(&receiver); 6125 cgen_->frame()->Push(&receiver);
6139 cgen_->frame()->Push(&value); 6126 cgen_->frame()->Push(&value);
6140 } 6127 }
6141 break; 6128 break;
6142 } 6129 }
6143 6130
6144 case KEYED: { 6131 case KEYED: {
6145 // TODO(1241834): Make sure that this it is safe to ignore the
6146 // distinction between expressions in a typeof and not in a typeof.
6147 Comment cmnt(masm, "[ Load from keyed Property"); 6132 Comment cmnt(masm, "[ Load from keyed Property");
6148 Variable* var = expression_->AsVariableProxy()->AsVariable(); 6133 Variable* var = expression_->AsVariableProxy()->AsVariable();
6149 bool is_global = var != NULL; 6134 bool is_global = var != NULL;
6150 ASSERT(!is_global || var->is_global()); 6135 ASSERT(!is_global || var->is_global());
6151 6136
6152 // Inline array load code if inside of a loop. We do not know 6137 // Inline array load code if inside of a loop. We do not know
6153 // the receiver map yet, so we initially generate the code with 6138 // the receiver map yet, so we initially generate the code with
6154 // a check against an invalid map. In the inline cache code, we 6139 // a check against an invalid map. In the inline cache code, we
6155 // patch the map check if appropriate. 6140 // patch the map check if appropriate.
6156 if (cgen_->loop_nesting() > 0) { 6141 if (cgen_->loop_nesting() > 0) {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
6255 } 6240 }
6256 break; 6241 break;
6257 } 6242 }
6258 6243
6259 default: 6244 default:
6260 UNREACHABLE(); 6245 UNREACHABLE();
6261 } 6246 }
6262 } 6247 }
6263 6248
6264 6249
6265 void Reference::TakeValue(TypeofState typeof_state) { 6250 void Reference::TakeValue() {
6266 // For non-constant frame-allocated slots, we invalidate the value in the 6251 // For non-constant frame-allocated slots, we invalidate the value in the
6267 // slot. For all others, we fall back on GetValue. 6252 // slot. For all others, we fall back on GetValue.
6268 ASSERT(!cgen_->in_spilled_code()); 6253 ASSERT(!cgen_->in_spilled_code());
6269 ASSERT(!is_illegal()); 6254 ASSERT(!is_illegal());
6270 if (type_ != SLOT) { 6255 if (type_ != SLOT) {
6271 GetValue(typeof_state); 6256 GetValue();
6272 return; 6257 return;
6273 } 6258 }
6274 6259
6275 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 6260 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
6276 ASSERT(slot != NULL); 6261 ASSERT(slot != NULL);
6277 if (slot->type() == Slot::LOOKUP || 6262 if (slot->type() == Slot::LOOKUP ||
6278 slot->type() == Slot::CONTEXT || 6263 slot->type() == Slot::CONTEXT ||
6279 slot->var()->mode() == Variable::CONST || 6264 slot->var()->mode() == Variable::CONST ||
6280 slot->is_arguments()) { 6265 slot->is_arguments()) {
6281 GetValue(typeof_state); 6266 GetValue();
6282 return; 6267 return;
6283 } 6268 }
6284 6269
6285 // Only non-constant, frame-allocated parameters and locals can 6270 // Only non-constant, frame-allocated parameters and locals can
6286 // reach here. Be careful not to use the optimizations for arguments 6271 // reach here. Be careful not to use the optimizations for arguments
6287 // object access since it may not have been initialized yet. 6272 // object access since it may not have been initialized yet.
6288 ASSERT(!slot->is_arguments()); 6273 ASSERT(!slot->is_arguments());
6289 if (slot->type() == Slot::PARAMETER) { 6274 if (slot->type() == Slot::PARAMETER) {
6290 cgen_->frame()->TakeParameterAt(slot->index()); 6275 cgen_->frame()->TakeParameterAt(slot->index());
6291 } else { 6276 } else {
(...skipping 1763 matching lines...) Expand 10 before | Expand all | Expand 10 after
8055 8040
8056 int CompareStub::MinorKey() { 8041 int CompareStub::MinorKey() {
8057 // Encode the two parameters in a unique 16 bit value. 8042 // Encode the two parameters in a unique 16 bit value.
8058 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 8043 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
8059 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 8044 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
8060 } 8045 }
8061 8046
8062 #undef __ 8047 #undef __
8063 8048
8064 } } // namespace v8::internal 8049 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/x64/codegen-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698