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

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

Issue 113458: First round of size reduction for JumpTargets. Reduce their size by... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 133 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
134 frame_->SpillAll(); 134 frame_->SpillAll();
135 __ int3(); 135 __ int3();
136 } 136 }
137 #endif 137 #endif
138 138
139 // Allocate space for locals and initialize them. 139 // Allocate space for locals and initialize them.
140 frame_->AllocateStackSlots(scope_->num_stack_slots()); 140 frame_->AllocateStackSlots(scope_->num_stack_slots());
141 // Initialize the function return target after the locals are set 141 // Initialize the function return target after the locals are set
142 // up, because it needs the expected frame height from the frame. 142 // up, because it needs the expected frame height from the frame.
143 function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL); 143 function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
144 function_return_is_shadowed_ = false; 144 function_return_is_shadowed_ = false;
145 145
146 // Allocate the arguments object and copy the parameters into it. 146 // Allocate the arguments object and copy the parameters into it.
147 if (scope_->arguments() != NULL) { 147 if (scope_->arguments() != NULL) {
148 ASSERT(scope_->arguments_shadow() != NULL); 148 ASSERT(scope_->arguments_shadow() != NULL);
149 Comment cmnt(masm_, "[ Allocate arguments object"); 149 Comment cmnt(masm_, "[ Allocate arguments object");
150 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 150 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
151 frame_->PushFunction(); 151 frame_->PushFunction();
152 frame_->PushReceiverSlotAddress(); 152 frame_->PushReceiverSlotAddress();
153 frame_->Push(Smi::FromInt(scope_->num_parameters())); 153 frame_->Push(Smi::FromInt(scope_->num_parameters()));
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 frame_->SpillAll(); 460 frame_->SpillAll();
461 set_in_spilled_code(true); 461 set_in_spilled_code(true);
462 } 462 }
463 463
464 464
465 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 465 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
466 #ifdef DEBUG 466 #ifdef DEBUG
467 int original_height = frame_->height(); 467 int original_height = frame_->height();
468 #endif 468 #endif
469 ASSERT(!in_spilled_code()); 469 ASSERT(!in_spilled_code());
470 JumpTarget true_target(this); 470 JumpTarget true_target;
471 JumpTarget false_target(this); 471 JumpTarget false_target;
472 ControlDestination dest(&true_target, &false_target, true); 472 ControlDestination dest(&true_target, &false_target, true);
473 LoadCondition(x, typeof_state, &dest, false); 473 LoadCondition(x, typeof_state, &dest, false);
474 474
475 if (dest.false_was_fall_through()) { 475 if (dest.false_was_fall_through()) {
476 // The false target was just bound. 476 // The false target was just bound.
477 JumpTarget loaded(this); 477 JumpTarget loaded;
478 frame_->Push(Factory::false_value()); 478 frame_->Push(Factory::false_value());
479 // There may be dangling jumps to the true target. 479 // There may be dangling jumps to the true target.
480 if (true_target.is_linked()) { 480 if (true_target.is_linked()) {
481 loaded.Jump(); 481 loaded.Jump();
482 true_target.Bind(); 482 true_target.Bind();
483 frame_->Push(Factory::true_value()); 483 frame_->Push(Factory::true_value());
484 loaded.Bind(); 484 loaded.Bind();
485 } 485 }
486 486
487 } else if (dest.is_used()) { 487 } else if (dest.is_used()) {
488 // There is true, and possibly false, control flow (with true as 488 // There is true, and possibly false, control flow (with true as
489 // the fall through). 489 // the fall through).
490 JumpTarget loaded(this); 490 JumpTarget loaded;
491 frame_->Push(Factory::true_value()); 491 frame_->Push(Factory::true_value());
492 if (false_target.is_linked()) { 492 if (false_target.is_linked()) {
493 loaded.Jump(); 493 loaded.Jump();
494 false_target.Bind(); 494 false_target.Bind();
495 frame_->Push(Factory::false_value()); 495 frame_->Push(Factory::false_value());
496 loaded.Bind(); 496 loaded.Bind();
497 } 497 }
498 498
499 } else { 499 } else {
500 // We have a valid value on top of the frame, but we still may 500 // We have a valid value on top of the frame, but we still may
501 // have dangling jumps to the true and false targets from nested 501 // have dangling jumps to the true and false targets from nested
502 // subexpressions (eg, the left subexpressions of the 502 // subexpressions (eg, the left subexpressions of the
503 // short-circuited boolean operators). 503 // short-circuited boolean operators).
504 ASSERT(has_valid_frame()); 504 ASSERT(has_valid_frame());
505 if (true_target.is_linked() || false_target.is_linked()) { 505 if (true_target.is_linked() || false_target.is_linked()) {
506 JumpTarget loaded(this); 506 JumpTarget loaded;
507 loaded.Jump(); // Don't lose the current TOS. 507 loaded.Jump(); // Don't lose the current TOS.
508 if (true_target.is_linked()) { 508 if (true_target.is_linked()) {
509 true_target.Bind(); 509 true_target.Bind();
510 frame_->Push(Factory::true_value()); 510 frame_->Push(Factory::true_value());
511 if (false_target.is_linked()) { 511 if (false_target.is_linked()) {
512 loaded.Jump(); 512 loaded.Jump();
513 } 513 }
514 } 514 }
515 if (false_target.is_linked()) { 515 if (false_target.is_linked()) {
516 false_target.Bind(); 516 false_target.Bind();
(...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after
1533 left_side = right_side; 1533 left_side = right_side;
1534 right_side = temp; 1534 right_side = temp;
1535 cc = ReverseCondition(cc); 1535 cc = ReverseCondition(cc);
1536 // This may reintroduce greater or less_equal as the value of cc. 1536 // This may reintroduce greater or less_equal as the value of cc.
1537 // CompareStub and the inline code both support all values of cc. 1537 // CompareStub and the inline code both support all values of cc.
1538 } 1538 }
1539 // Implement comparison against a constant Smi, inlining the case 1539 // Implement comparison against a constant Smi, inlining the case
1540 // where both sides are Smis. 1540 // where both sides are Smis.
1541 left_side.ToRegister(); 1541 left_side.ToRegister();
1542 ASSERT(left_side.is_valid()); 1542 ASSERT(left_side.is_valid());
1543 JumpTarget is_smi(this); 1543 JumpTarget is_smi;
1544 __ test(left_side.reg(), Immediate(kSmiTagMask)); 1544 __ test(left_side.reg(), Immediate(kSmiTagMask));
1545 is_smi.Branch(zero, &left_side, &right_side, taken); 1545 is_smi.Branch(zero, &left_side, &right_side, taken);
1546 1546
1547 // Setup and call the compare stub, which expects its arguments 1547 // Setup and call the compare stub, which expects its arguments
1548 // in registers. 1548 // in registers.
1549 CompareStub stub(cc, strict); 1549 CompareStub stub(cc, strict);
1550 Result result = frame_->CallStub(&stub, &left_side, &right_side); 1550 Result result = frame_->CallStub(&stub, &left_side, &right_side);
1551 result.ToRegister(); 1551 result.ToRegister();
1552 __ cmp(result.reg(), 0); 1552 __ cmp(result.reg(), 0);
1553 result.Unuse(); 1553 result.Unuse();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1604 operand.Unuse(); 1604 operand.Unuse();
1605 dest->Split(not_zero); 1605 dest->Split(not_zero);
1606 } 1606 }
1607 } else { // Neither side is a constant Smi or null. 1607 } else { // Neither side is a constant Smi or null.
1608 // If either side is a non-smi constant, skip the smi check. 1608 // If either side is a non-smi constant, skip the smi check.
1609 bool known_non_smi = 1609 bool known_non_smi =
1610 (left_side.is_constant() && !left_side.handle()->IsSmi()) || 1610 (left_side.is_constant() && !left_side.handle()->IsSmi()) ||
1611 (right_side.is_constant() && !right_side.handle()->IsSmi()); 1611 (right_side.is_constant() && !right_side.handle()->IsSmi());
1612 left_side.ToRegister(); 1612 left_side.ToRegister();
1613 right_side.ToRegister(); 1613 right_side.ToRegister();
1614 JumpTarget is_smi(this); 1614 JumpTarget is_smi;
1615 if (!known_non_smi) { 1615 if (!known_non_smi) {
1616 // Check for the smi case. 1616 // Check for the smi case.
1617 Result temp = allocator_->Allocate(); 1617 Result temp = allocator_->Allocate();
1618 ASSERT(temp.is_valid()); 1618 ASSERT(temp.is_valid());
1619 __ mov(temp.reg(), left_side.reg()); 1619 __ mov(temp.reg(), left_side.reg());
1620 __ or_(temp.reg(), Operand(right_side.reg())); 1620 __ or_(temp.reg(), Operand(right_side.reg()));
1621 __ test(temp.reg(), Immediate(kSmiTagMask)); 1621 __ test(temp.reg(), Immediate(kSmiTagMask));
1622 temp.Unuse(); 1622 temp.Unuse();
1623 is_smi.Branch(zero, &left_side, &right_side, taken); 1623 is_smi.Branch(zero, &left_side, &right_side, taken);
1624 } 1624 }
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1749 for (int i = 0; has_valid_frame() && i < statements->length(); i++) { 1749 for (int i = 0; has_valid_frame() && i < statements->length(); i++) {
1750 Visit(statements->at(i)); 1750 Visit(statements->at(i));
1751 } 1751 }
1752 } 1752 }
1753 1753
1754 1754
1755 void CodeGenerator::VisitBlock(Block* node) { 1755 void CodeGenerator::VisitBlock(Block* node) {
1756 ASSERT(!in_spilled_code()); 1756 ASSERT(!in_spilled_code());
1757 Comment cmnt(masm_, "[ Block"); 1757 Comment cmnt(masm_, "[ Block");
1758 CodeForStatementPosition(node); 1758 CodeForStatementPosition(node);
1759 node->break_target()->Initialize(this); 1759 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1760 VisitStatements(node->statements()); 1760 VisitStatements(node->statements());
1761 if (node->break_target()->is_linked()) { 1761 if (node->break_target()->is_linked()) {
1762 node->break_target()->Bind(); 1762 node->break_target()->Bind();
1763 } 1763 }
1764 node->break_target()->Unuse(); 1764 node->break_target()->Unuse();
1765 } 1765 }
1766 1766
1767 1767
1768 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1768 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1769 frame_->Push(pairs); 1769 frame_->Push(pairs);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1863 1863
1864 void CodeGenerator::VisitIfStatement(IfStatement* node) { 1864 void CodeGenerator::VisitIfStatement(IfStatement* node) {
1865 ASSERT(!in_spilled_code()); 1865 ASSERT(!in_spilled_code());
1866 Comment cmnt(masm_, "[ IfStatement"); 1866 Comment cmnt(masm_, "[ IfStatement");
1867 // Generate different code depending on which parts of the if statement 1867 // Generate different code depending on which parts of the if statement
1868 // are present or not. 1868 // are present or not.
1869 bool has_then_stm = node->HasThenStatement(); 1869 bool has_then_stm = node->HasThenStatement();
1870 bool has_else_stm = node->HasElseStatement(); 1870 bool has_else_stm = node->HasElseStatement();
1871 1871
1872 CodeForStatementPosition(node); 1872 CodeForStatementPosition(node);
1873 JumpTarget exit(this); 1873 JumpTarget exit;
1874 if (has_then_stm && has_else_stm) { 1874 if (has_then_stm && has_else_stm) {
1875 JumpTarget then(this); 1875 JumpTarget then;
1876 JumpTarget else_(this); 1876 JumpTarget else_;
1877 ControlDestination dest(&then, &else_, true); 1877 ControlDestination dest(&then, &else_, true);
1878 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 1878 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
1879 1879
1880 if (dest.false_was_fall_through()) { 1880 if (dest.false_was_fall_through()) {
1881 // The else target was bound, so we compile the else part first. 1881 // The else target was bound, so we compile the else part first.
1882 Visit(node->else_statement()); 1882 Visit(node->else_statement());
1883 1883
1884 // We may have dangling jumps to the then part. 1884 // We may have dangling jumps to the then part.
1885 if (then.is_linked()) { 1885 if (then.is_linked()) {
1886 if (has_valid_frame()) exit.Jump(); 1886 if (has_valid_frame()) exit.Jump();
1887 then.Bind(); 1887 then.Bind();
1888 Visit(node->then_statement()); 1888 Visit(node->then_statement());
1889 } 1889 }
1890 } else { 1890 } else {
1891 // The then target was bound, so we compile the then part first. 1891 // The then target was bound, so we compile the then part first.
1892 Visit(node->then_statement()); 1892 Visit(node->then_statement());
1893 1893
1894 if (else_.is_linked()) { 1894 if (else_.is_linked()) {
1895 if (has_valid_frame()) exit.Jump(); 1895 if (has_valid_frame()) exit.Jump();
1896 else_.Bind(); 1896 else_.Bind();
1897 Visit(node->else_statement()); 1897 Visit(node->else_statement());
1898 } 1898 }
1899 } 1899 }
1900 1900
1901 } else if (has_then_stm) { 1901 } else if (has_then_stm) {
1902 ASSERT(!has_else_stm); 1902 ASSERT(!has_else_stm);
1903 JumpTarget then(this); 1903 JumpTarget then;
1904 ControlDestination dest(&then, &exit, true); 1904 ControlDestination dest(&then, &exit, true);
1905 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 1905 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
1906 1906
1907 if (dest.false_was_fall_through()) { 1907 if (dest.false_was_fall_through()) {
1908 // The exit label was bound. We may have dangling jumps to the 1908 // The exit label was bound. We may have dangling jumps to the
1909 // then part. 1909 // then part.
1910 if (then.is_linked()) { 1910 if (then.is_linked()) {
1911 exit.Unuse(); 1911 exit.Unuse();
1912 exit.Jump(); 1912 exit.Jump();
1913 then.Bind(); 1913 then.Bind();
1914 Visit(node->then_statement()); 1914 Visit(node->then_statement());
1915 } 1915 }
1916 } else { 1916 } else {
1917 // The then label was bound. 1917 // The then label was bound.
1918 Visit(node->then_statement()); 1918 Visit(node->then_statement());
1919 } 1919 }
1920 1920
1921 } else if (has_else_stm) { 1921 } else if (has_else_stm) {
1922 ASSERT(!has_then_stm); 1922 ASSERT(!has_then_stm);
1923 JumpTarget else_(this); 1923 JumpTarget else_;
1924 ControlDestination dest(&exit, &else_, false); 1924 ControlDestination dest(&exit, &else_, false);
1925 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 1925 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
1926 1926
1927 if (dest.true_was_fall_through()) { 1927 if (dest.true_was_fall_through()) {
1928 // The exit label was bound. We may have dangling jumps to the 1928 // The exit label was bound. We may have dangling jumps to the
1929 // else part. 1929 // else part.
1930 if (else_.is_linked()) { 1930 if (else_.is_linked()) {
1931 exit.Unuse(); 1931 exit.Unuse();
1932 exit.Jump(); 1932 exit.Jump();
1933 else_.Bind(); 1933 else_.Bind();
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
2080 Vector<Label*> case_targets, 2080 Vector<Label*> case_targets,
2081 Vector<Label> case_labels) { 2081 Vector<Label> case_labels) {
2082 // Notice: Internal references, used by both the jmp instruction and 2082 // Notice: Internal references, used by both the jmp instruction and
2083 // the table entries, need to be relocated if the buffer grows. This 2083 // the table entries, need to be relocated if the buffer grows. This
2084 // prevents the forward use of Labels, since a displacement cannot 2084 // prevents the forward use of Labels, since a displacement cannot
2085 // survive relocation, and it also cannot safely be distinguished 2085 // survive relocation, and it also cannot safely be distinguished
2086 // from a real address. Instead we put in zero-values as 2086 // from a real address. Instead we put in zero-values as
2087 // placeholders, and fill in the addresses after the labels have been 2087 // placeholders, and fill in the addresses after the labels have been
2088 // bound. 2088 // bound.
2089 2089
2090 JumpTarget setup_default(this); 2090 JumpTarget setup_default;
2091 JumpTarget is_smi(this); 2091 JumpTarget is_smi;
2092 2092
2093 // A non-null default label pointer indicates a default case among 2093 // A non-null default label pointer indicates a default case among
2094 // the case labels. Otherwise we use the break target as a 2094 // the case labels. Otherwise we use the break target as a
2095 // "default". 2095 // "default".
2096 JumpTarget* default_target = 2096 JumpTarget* default_target =
2097 (default_label == NULL) ? node->break_target() : &setup_default; 2097 (default_label == NULL) ? node->break_target() : &setup_default;
2098 2098
2099 // Test whether input is a smi. 2099 // Test whether input is a smi.
2100 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 2100 ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
2101 Result switch_value = frame_->Pop(); 2101 Result switch_value = frame_->Pop();
(...skipping 24 matching lines...) Expand all
2126 __ test(smi_value.reg(), Immediate(0x80000000 | kSmiTagMask)); 2126 __ test(smi_value.reg(), Immediate(0x80000000 | kSmiTagMask));
2127 default_target->Branch(not_equal, not_taken); 2127 default_target->Branch(not_equal, not_taken);
2128 __ cmp(smi_value.reg(), range << kSmiTagSize); 2128 __ cmp(smi_value.reg(), range << kSmiTagSize);
2129 default_target->Branch(greater_equal, not_taken); 2129 default_target->Branch(greater_equal, not_taken);
2130 2130
2131 // The expected frame at all the case labels is a version of the 2131 // The expected frame at all the case labels is a version of the
2132 // current one (the bidirectional entry frame, which an arbitrary 2132 // current one (the bidirectional entry frame, which an arbitrary
2133 // frame of the correct height can be merged to). Keep a copy to 2133 // frame of the correct height can be merged to). Keep a copy to
2134 // restore at the start of every label. Create a jump target and 2134 // restore at the start of every label. Create a jump target and
2135 // bind it to set its entry frame properly. 2135 // bind it to set its entry frame properly.
2136 JumpTarget entry_target(this, JumpTarget::BIDIRECTIONAL); 2136 JumpTarget entry_target(JumpTarget::BIDIRECTIONAL);
2137 entry_target.Bind(&smi_value); 2137 entry_target.Bind(&smi_value);
2138 VirtualFrame* start_frame = new VirtualFrame(frame_); 2138 VirtualFrame* start_frame = new VirtualFrame(frame_);
2139 2139
2140 // 0 is placeholder. 2140 // 0 is placeholder.
2141 // Jump to the address at table_address + 2 * smi_value.reg(). 2141 // Jump to the address at table_address + 2 * smi_value.reg().
2142 // The target of the jump is read from table_address + 4 * switch_value. 2142 // The target of the jump is read from table_address + 4 * switch_value.
2143 // The Smi encoding of smi_value.reg() is 2 * switch_value. 2143 // The Smi encoding of smi_value.reg() is 2 * switch_value.
2144 smi_value.ToRegister(); 2144 smi_value.ToRegister();
2145 __ jmp(Operand(smi_value.reg(), smi_value.reg(), 2145 __ jmp(Operand(smi_value.reg(), smi_value.reg(),
2146 times_1, 0x0, RelocInfo::INTERNAL_REFERENCE)); 2146 times_1, 0x0, RelocInfo::INTERNAL_REFERENCE));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2183 __ WriteInternalReference(entry_pos, *case_targets[i]); 2183 __ WriteInternalReference(entry_pos, *case_targets[i]);
2184 } 2184 }
2185 } 2185 }
2186 } 2186 }
2187 2187
2188 2188
2189 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { 2189 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
2190 ASSERT(!in_spilled_code()); 2190 ASSERT(!in_spilled_code());
2191 Comment cmnt(masm_, "[ SwitchStatement"); 2191 Comment cmnt(masm_, "[ SwitchStatement");
2192 CodeForStatementPosition(node); 2192 CodeForStatementPosition(node);
2193 node->break_target()->Initialize(this); 2193 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
2194 2194
2195 // Compile the switch value. 2195 // Compile the switch value.
2196 Load(node->tag()); 2196 Load(node->tag());
2197 2197
2198 if (TryGenerateFastCaseSwitchStatement(node)) { 2198 if (TryGenerateFastCaseSwitchStatement(node)) {
2199 return; 2199 return;
2200 } 2200 }
2201 2201
2202 ZoneList<CaseClause*>* cases = node->cases(); 2202 ZoneList<CaseClause*>* cases = node->cases();
2203 int length = cases->length(); 2203 int length = cases->length();
2204 CaseClause* default_clause = NULL; 2204 CaseClause* default_clause = NULL;
2205 2205
2206 JumpTarget next_test(this); 2206 JumpTarget next_test;
2207 // Compile the case label expressions and comparisons. Exit early 2207 // Compile the case label expressions and comparisons. Exit early
2208 // if a comparison is unconditionally true. The target next_test is 2208 // if a comparison is unconditionally true. The target next_test is
2209 // bound before the loop in order to indicate control flow to the 2209 // bound before the loop in order to indicate control flow to the
2210 // first comparison. 2210 // first comparison.
2211 next_test.Bind(); 2211 next_test.Bind();
2212 for (int i = 0; i < length && !next_test.is_unused(); i++) { 2212 for (int i = 0; i < length && !next_test.is_unused(); i++) {
2213 CaseClause* clause = cases->at(i); 2213 CaseClause* clause = cases->at(i);
2214 clause->body_target()->Initialize(this);
2215 // The default is not a test, but remember it for later. 2214 // The default is not a test, but remember it for later.
2216 if (clause->is_default()) { 2215 if (clause->is_default()) {
2217 default_clause = clause; 2216 default_clause = clause;
2218 continue; 2217 continue;
2219 } 2218 }
2220 2219
2221 Comment cmnt(masm_, "[ Case comparison"); 2220 Comment cmnt(masm_, "[ Case comparison");
2222 // We recycle the same target next_test for each test. Bind it if 2221 // We recycle the same target next_test for each test. Bind it if
2223 // the previous test has not done so and then unuse it for the 2222 // the previous test has not done so and then unuse it for the
2224 // loop. 2223 // loop.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2275 if (clause->body_target()->is_linked() || has_valid_frame()) { 2274 if (clause->body_target()->is_linked() || has_valid_frame()) {
2276 if (clause->body_target()->is_linked()) { 2275 if (clause->body_target()->is_linked()) {
2277 if (has_valid_frame()) { 2276 if (has_valid_frame()) {
2278 // If we have both a jump to the test and a fall through, put 2277 // If we have both a jump to the test and a fall through, put
2279 // a jump on the fall through path to avoid the dropping of 2278 // a jump on the fall through path to avoid the dropping of
2280 // the switch value on the test path. The exception is the 2279 // the switch value on the test path. The exception is the
2281 // default which has already had the switch value dropped. 2280 // default which has already had the switch value dropped.
2282 if (clause->is_default()) { 2281 if (clause->is_default()) {
2283 clause->body_target()->Bind(); 2282 clause->body_target()->Bind();
2284 } else { 2283 } else {
2285 JumpTarget body(this); 2284 JumpTarget body;
2286 body.Jump(); 2285 body.Jump();
2287 clause->body_target()->Bind(); 2286 clause->body_target()->Bind();
2288 frame_->Drop(); 2287 frame_->Drop();
2289 body.Bind(); 2288 body.Bind();
2290 } 2289 }
2291 } else { 2290 } else {
2292 // No fall through to worry about. 2291 // No fall through to worry about.
2293 clause->body_target()->Bind(); 2292 clause->body_target()->Bind();
2294 if (!clause->is_default()) { 2293 if (!clause->is_default()) {
2295 frame_->Drop(); 2294 frame_->Drop();
(...skipping 17 matching lines...) Expand all
2313 node->break_target()->Bind(); 2312 node->break_target()->Bind();
2314 } 2313 }
2315 node->break_target()->Unuse(); 2314 node->break_target()->Unuse();
2316 } 2315 }
2317 2316
2318 2317
2319 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 2318 void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
2320 ASSERT(!in_spilled_code()); 2319 ASSERT(!in_spilled_code());
2321 Comment cmnt(masm_, "[ LoopStatement"); 2320 Comment cmnt(masm_, "[ LoopStatement");
2322 CodeForStatementPosition(node); 2321 CodeForStatementPosition(node);
2323 node->break_target()->Initialize(this); 2322 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
2324 2323
2325 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a 2324 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
2326 // known result for the test expression, with no side effects. 2325 // known result for the test expression, with no side effects.
2327 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; 2326 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW;
2328 if (node->cond() == NULL) { 2327 if (node->cond() == NULL) {
2329 ASSERT(node->type() == LoopStatement::FOR_LOOP); 2328 ASSERT(node->type() == LoopStatement::FOR_LOOP);
2330 info = ALWAYS_TRUE; 2329 info = ALWAYS_TRUE;
2331 } else { 2330 } else {
2332 Literal* lit = node->cond()->AsLiteral(); 2331 Literal* lit = node->cond()->AsLiteral();
2333 if (lit != NULL) { 2332 if (lit != NULL) {
2334 if (lit->IsTrue()) { 2333 if (lit->IsTrue()) {
2335 info = ALWAYS_TRUE; 2334 info = ALWAYS_TRUE;
2336 } else if (lit->IsFalse()) { 2335 } else if (lit->IsFalse()) {
2337 info = ALWAYS_FALSE; 2336 info = ALWAYS_FALSE;
2338 } 2337 }
2339 } 2338 }
2340 } 2339 }
2341 2340
2342 switch (node->type()) { 2341 switch (node->type()) {
2343 case LoopStatement::DO_LOOP: { 2342 case LoopStatement::DO_LOOP: {
2344 JumpTarget body(this, JumpTarget::BIDIRECTIONAL); 2343 JumpTarget body(JumpTarget::BIDIRECTIONAL);
2345 IncrementLoopNesting(); 2344 IncrementLoopNesting();
2346 2345
2347 // Label the top of the loop for the backward jump if necessary. 2346 // Label the top of the loop for the backward jump if necessary.
2348 if (info == ALWAYS_TRUE) { 2347 if (info == ALWAYS_TRUE) {
2349 // Use the continue target. 2348 // Use the continue target.
2350 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 2349 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2351 node->continue_target()->Bind(); 2350 node->continue_target()->Bind();
2352 } else if (info == ALWAYS_FALSE) { 2351 } else if (info == ALWAYS_FALSE) {
2353 // No need to label it. 2352 // No need to label it.
2354 node->continue_target()->Initialize(this); 2353 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2355 } else { 2354 } else {
2356 // Continue is the test, so use the backward body target. 2355 // Continue is the test, so use the backward body target.
2357 ASSERT(info == DONT_KNOW); 2356 ASSERT(info == DONT_KNOW);
2358 node->continue_target()->Initialize(this); 2357 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2359 body.Bind(); 2358 body.Bind();
2360 } 2359 }
2361 2360
2362 CheckStack(); // TODO(1222600): ignore if body contains calls. 2361 CheckStack(); // TODO(1222600): ignore if body contains calls.
2363 Visit(node->body()); 2362 Visit(node->body());
2364 2363
2365 // Compile the test. 2364 // Compile the test.
2366 if (info == ALWAYS_TRUE) { 2365 if (info == ALWAYS_TRUE) {
2367 // If control flow can fall off the end of the body, jump back 2366 // If control flow can fall off the end of the body, jump back
2368 // to the top and bind the break target at the exit. 2367 // to the top and bind the break target at the exit.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2407 bool test_at_bottom = !node->may_have_function_literal(); 2406 bool test_at_bottom = !node->may_have_function_literal();
2408 2407
2409 IncrementLoopNesting(); 2408 IncrementLoopNesting();
2410 2409
2411 // If the condition is always false and has no side effects, we 2410 // If the condition is always false and has no side effects, we
2412 // do not need to compile anything. 2411 // do not need to compile anything.
2413 if (info == ALWAYS_FALSE) break; 2412 if (info == ALWAYS_FALSE) break;
2414 2413
2415 JumpTarget body; 2414 JumpTarget body;
2416 if (test_at_bottom) { 2415 if (test_at_bottom) {
2417 body.Initialize(this, JumpTarget::BIDIRECTIONAL); 2416 body.set_direction(JumpTarget::BIDIRECTIONAL);
2418 } else {
2419 body.Initialize(this);
2420 } 2417 }
2421 2418
2422 // Based on the condition analysis, compile the test as necessary. 2419 // Based on the condition analysis, compile the test as necessary.
2423 if (info == ALWAYS_TRUE) { 2420 if (info == ALWAYS_TRUE) {
2424 // We will not compile the test expression. Label the top of 2421 // We will not compile the test expression. Label the top of
2425 // the loop with the continue target. 2422 // the loop with the continue target.
2426 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 2423 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2427 node->continue_target()->Bind(); 2424 node->continue_target()->Bind();
2428 } else { 2425 } else {
2429 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here. 2426 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
2430 if (test_at_bottom) { 2427 if (test_at_bottom) {
2431 // Continue is the test at the bottom, no need to label the 2428 // Continue is the test at the bottom, no need to label the
2432 // test at the top. The body is a backward target. 2429 // test at the top. The body is a backward target.
2433 node->continue_target()->Initialize(this); 2430 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2434 } else { 2431 } else {
2435 // Label the test at the top as the continue target. The 2432 // Label the test at the top as the continue target. The
2436 // body is a forward-only target. 2433 // body is a forward-only target.
2437 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 2434 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2438 node->continue_target()->Bind(); 2435 node->continue_target()->Bind();
2439 } 2436 }
2440 // Compile the test with the body as the true target and 2437 // Compile the test with the body as the true target and
2441 // preferred fall-through and with the break target as the 2438 // preferred fall-through and with the break target as the
2442 // false target. 2439 // false target.
2443 ControlDestination dest(&body, node->break_target(), true); 2440 ControlDestination dest(&body, node->break_target(), true);
2444 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2441 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2445 2442
2446 if (dest.false_was_fall_through()) { 2443 if (dest.false_was_fall_through()) {
2447 // If we got the break target as fall-through, the test may 2444 // If we got the break target as fall-through, the test may
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2510 } 2507 }
2511 2508
2512 IncrementLoopNesting(); 2509 IncrementLoopNesting();
2513 2510
2514 // If the condition is always false and has no side effects, we 2511 // If the condition is always false and has no side effects, we
2515 // do not need to compile anything else. 2512 // do not need to compile anything else.
2516 if (info == ALWAYS_FALSE) break; 2513 if (info == ALWAYS_FALSE) break;
2517 2514
2518 // Target for backward edge if no test at the bottom, otherwise 2515 // Target for backward edge if no test at the bottom, otherwise
2519 // unused. 2516 // unused.
2520 JumpTarget loop(this, JumpTarget::BIDIRECTIONAL); 2517 JumpTarget loop(JumpTarget::BIDIRECTIONAL);
2521 2518
2522 // Target for backward edge if there is a test at the bottom, 2519 // Target for backward edge if there is a test at the bottom,
2523 // otherwise used as target for test at the top. 2520 // otherwise used as target for test at the top.
2524 JumpTarget body; 2521 JumpTarget body;
2525 if (test_at_bottom) { 2522 if (test_at_bottom) {
2526 body.Initialize(this, JumpTarget::BIDIRECTIONAL); 2523 body.set_direction(JumpTarget::BIDIRECTIONAL);
2527 } else {
2528 body.Initialize(this);
2529 } 2524 }
2530 2525
2531 // Based on the condition analysis, compile the test as necessary. 2526 // Based on the condition analysis, compile the test as necessary.
2532 if (info == ALWAYS_TRUE) { 2527 if (info == ALWAYS_TRUE) {
2533 // We will not compile the test expression. Label the top of 2528 // We will not compile the test expression. Label the top of
2534 // the loop. 2529 // the loop.
2535 if (node->next() == NULL) { 2530 if (node->next() == NULL) {
2536 // Use the continue target if there is no update expression. 2531 // Use the continue target if there is no update expression.
2537 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 2532 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2538 node->continue_target()->Bind(); 2533 node->continue_target()->Bind();
2539 } else { 2534 } else {
2540 // Otherwise use the backward loop target. 2535 // Otherwise use the backward loop target.
2541 node->continue_target()->Initialize(this); 2536 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2542 loop.Bind(); 2537 loop.Bind();
2543 } 2538 }
2544 } else { 2539 } else {
2545 ASSERT(info == DONT_KNOW); 2540 ASSERT(info == DONT_KNOW);
2546 if (test_at_bottom) { 2541 if (test_at_bottom) {
2547 // Continue is either the update expression or the test at 2542 // Continue is either the update expression or the test at
2548 // the bottom, no need to label the test at the top. 2543 // the bottom, no need to label the test at the top.
2549 node->continue_target()->Initialize(this); 2544 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2550 } else if (node->next() == NULL) { 2545 } else if (node->next() == NULL) {
2551 // We are not recompiling the test at the bottom and there 2546 // We are not recompiling the test at the bottom and there
2552 // is no update expression. 2547 // is no update expression.
2553 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 2548 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2554 node->continue_target()->Bind(); 2549 node->continue_target()->Bind();
2555 } else { 2550 } else {
2556 // We are not recompiling the test at the bottom and there 2551 // We are not recompiling the test at the bottom and there
2557 // is an update expression. 2552 // is an update expression.
2558 node->continue_target()->Initialize(this); 2553 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2559 loop.Bind(); 2554 loop.Bind();
2560 } 2555 }
2561 2556
2562 // Compile the test with the body as the true target and 2557 // Compile the test with the body as the true target and
2563 // preferred fall-through and with the break target as the 2558 // preferred fall-through and with the break target as the
2564 // false target. 2559 // false target.
2565 ControlDestination dest(&body, node->break_target(), true); 2560 ControlDestination dest(&body, node->break_target(), true);
2566 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2561 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2567 2562
2568 if (dest.false_was_fall_through()) { 2563 if (dest.false_was_fall_through()) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
2652 node->break_target()->Unuse(); 2647 node->break_target()->Unuse();
2653 } 2648 }
2654 2649
2655 2650
2656 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 2651 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
2657 ASSERT(!in_spilled_code()); 2652 ASSERT(!in_spilled_code());
2658 VirtualFrame::SpilledScope spilled_scope(this); 2653 VirtualFrame::SpilledScope spilled_scope(this);
2659 Comment cmnt(masm_, "[ ForInStatement"); 2654 Comment cmnt(masm_, "[ ForInStatement");
2660 CodeForStatementPosition(node); 2655 CodeForStatementPosition(node);
2661 2656
2662 JumpTarget primitive(this); 2657 JumpTarget primitive;
2663 JumpTarget jsobject(this); 2658 JumpTarget jsobject;
2664 JumpTarget fixed_array(this); 2659 JumpTarget fixed_array;
2665 JumpTarget entry(this, JumpTarget::BIDIRECTIONAL); 2660 JumpTarget entry(JumpTarget::BIDIRECTIONAL);
2666 JumpTarget end_del_check(this); 2661 JumpTarget end_del_check;
2667 JumpTarget exit(this); 2662 JumpTarget exit;
2668 2663
2669 // Get the object to enumerate over (converted to JSObject). 2664 // Get the object to enumerate over (converted to JSObject).
2670 LoadAndSpill(node->enumerable()); 2665 LoadAndSpill(node->enumerable());
2671 2666
2672 // Both SpiderMonkey and kjs ignore null and undefined in contrast 2667 // Both SpiderMonkey and kjs ignore null and undefined in contrast
2673 // to the specification. 12.6.4 mandates a call to ToObject. 2668 // to the specification. 12.6.4 mandates a call to ToObject.
2674 frame_->EmitPop(eax); 2669 frame_->EmitPop(eax);
2675 2670
2676 // eax: value to be iterated over 2671 // eax: value to be iterated over
2677 __ cmp(eax, Factory::undefined_value()); 2672 __ cmp(eax, Factory::undefined_value());
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2742 // Push the length of the array and the initial index onto the stack. 2737 // Push the length of the array and the initial index onto the stack.
2743 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); 2738 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
2744 __ shl(eax, kSmiTagSize); 2739 __ shl(eax, kSmiTagSize);
2745 frame_->EmitPush(eax); // <- slot 1 2740 frame_->EmitPush(eax); // <- slot 1
2746 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0 2741 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0
2747 2742
2748 // Condition. 2743 // Condition.
2749 entry.Bind(); 2744 entry.Bind();
2750 // Grab the current frame's height for the break and continue 2745 // Grab the current frame's height for the break and continue
2751 // targets only after all the state is pushed on the frame. 2746 // targets only after all the state is pushed on the frame.
2752 node->break_target()->Initialize(this); 2747 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
2753 node->continue_target()->Initialize(this); 2748 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2754 2749
2755 __ mov(eax, frame_->ElementAt(0)); // load the current count 2750 __ mov(eax, frame_->ElementAt(0)); // load the current count
2756 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length 2751 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length
2757 node->break_target()->Branch(above_equal); 2752 node->break_target()->Branch(above_equal);
2758 2753
2759 // Get the i'th entry of the array. 2754 // Get the i'th entry of the array.
2760 __ mov(edx, frame_->ElementAt(2)); 2755 __ mov(edx, frame_->ElementAt(2));
2761 __ mov(ebx, Operand(edx, eax, times_2, 2756 __ mov(ebx, Operand(edx, eax, times_2,
2762 FixedArray::kHeaderSize - kHeapObjectTag)); 2757 FixedArray::kHeaderSize - kHeapObjectTag));
2763 2758
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2842 node->break_target()->Unuse(); 2837 node->break_target()->Unuse();
2843 } 2838 }
2844 2839
2845 2840
2846 void CodeGenerator::VisitTryCatch(TryCatch* node) { 2841 void CodeGenerator::VisitTryCatch(TryCatch* node) {
2847 ASSERT(!in_spilled_code()); 2842 ASSERT(!in_spilled_code());
2848 VirtualFrame::SpilledScope spilled_scope(this); 2843 VirtualFrame::SpilledScope spilled_scope(this);
2849 Comment cmnt(masm_, "[ TryCatch"); 2844 Comment cmnt(masm_, "[ TryCatch");
2850 CodeForStatementPosition(node); 2845 CodeForStatementPosition(node);
2851 2846
2852 JumpTarget try_block(this); 2847 JumpTarget try_block;
2853 JumpTarget exit(this); 2848 JumpTarget exit;
2854 2849
2855 try_block.Call(); 2850 try_block.Call();
2856 // --- Catch block --- 2851 // --- Catch block ---
2857 frame_->EmitPush(eax); 2852 frame_->EmitPush(eax);
2858 2853
2859 // Store the caught exception in the catch variable. 2854 // Store the caught exception in the catch variable.
2860 { Reference ref(this, node->catch_var()); 2855 { Reference ref(this, node->catch_var());
2861 ASSERT(ref.is_slot()); 2856 ASSERT(ref.is_slot());
2862 // Load the exception to the top of the stack. Here we make use of the 2857 // Load the exception to the top of the stack. Here we make use of the
2863 // convenient property that it doesn't matter whether a value is 2858 // convenient property that it doesn't matter whether a value is
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
2986 ASSERT(!in_spilled_code()); 2981 ASSERT(!in_spilled_code());
2987 VirtualFrame::SpilledScope spilled_scope(this); 2982 VirtualFrame::SpilledScope spilled_scope(this);
2988 Comment cmnt(masm_, "[ TryFinally"); 2983 Comment cmnt(masm_, "[ TryFinally");
2989 CodeForStatementPosition(node); 2984 CodeForStatementPosition(node);
2990 2985
2991 // State: Used to keep track of reason for entering the finally 2986 // State: Used to keep track of reason for entering the finally
2992 // block. Should probably be extended to hold information for 2987 // block. Should probably be extended to hold information for
2993 // break/continue from within the try block. 2988 // break/continue from within the try block.
2994 enum { FALLING, THROWING, JUMPING }; 2989 enum { FALLING, THROWING, JUMPING };
2995 2990
2996 JumpTarget try_block(this); 2991 JumpTarget try_block;
2997 JumpTarget finally_block(this); 2992 JumpTarget finally_block;
2998 2993
2999 try_block.Call(); 2994 try_block.Call();
3000 2995
3001 frame_->EmitPush(eax); 2996 frame_->EmitPush(eax);
3002 // In case of thrown exceptions, this is where we continue. 2997 // In case of thrown exceptions, this is where we continue.
3003 __ Set(ecx, Immediate(Smi::FromInt(THROWING))); 2998 __ Set(ecx, Immediate(Smi::FromInt(THROWING)));
3004 finally_block.Jump(); 2999 finally_block.Jump();
3005 3000
3006 // --- Try block --- 3001 // --- Try block ---
3007 try_block.Bind(); 3002 try_block.Bind();
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
3139 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); 3134 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i)));
3140 if (i == kReturnShadowIndex) { 3135 if (i == kReturnShadowIndex) {
3141 // The return value is (already) in eax. 3136 // The return value is (already) in eax.
3142 Result return_value = allocator_->Allocate(eax); 3137 Result return_value = allocator_->Allocate(eax);
3143 ASSERT(return_value.is_valid()); 3138 ASSERT(return_value.is_valid());
3144 if (function_return_is_shadowed_) { 3139 if (function_return_is_shadowed_) {
3145 original->Branch(equal, &return_value); 3140 original->Branch(equal, &return_value);
3146 } else { 3141 } else {
3147 // Branch around the preparation for return which may emit 3142 // Branch around the preparation for return which may emit
3148 // code. 3143 // code.
3149 JumpTarget skip(this); 3144 JumpTarget skip;
3150 skip.Branch(not_equal); 3145 skip.Branch(not_equal);
3151 frame_->PrepareForReturn(); 3146 frame_->PrepareForReturn();
3152 original->Jump(&return_value); 3147 original->Jump(&return_value);
3153 skip.Bind(); 3148 skip.Bind();
3154 } 3149 }
3155 } else { 3150 } else {
3156 original->Branch(equal); 3151 original->Branch(equal);
3157 } 3152 }
3158 } 3153 }
3159 } 3154 }
3160 3155
3161 if (has_valid_frame()) { 3156 if (has_valid_frame()) {
3162 // Check if we need to rethrow the exception. 3157 // Check if we need to rethrow the exception.
3163 JumpTarget exit(this); 3158 JumpTarget exit;
3164 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING))); 3159 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING)));
3165 exit.Branch(not_equal); 3160 exit.Branch(not_equal);
3166 3161
3167 // Rethrow exception. 3162 // Rethrow exception.
3168 frame_->EmitPush(eax); // undo pop from above 3163 frame_->EmitPush(eax); // undo pop from above
3169 frame_->CallRuntime(Runtime::kReThrow, 1); 3164 frame_->CallRuntime(Runtime::kReThrow, 1);
3170 3165
3171 // Done. 3166 // Done.
3172 exit.Bind(); 3167 exit.Bind();
3173 } 3168 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3213 3208
3214 void CodeGenerator::VisitFunctionBoilerplateLiteral( 3209 void CodeGenerator::VisitFunctionBoilerplateLiteral(
3215 FunctionBoilerplateLiteral* node) { 3210 FunctionBoilerplateLiteral* node) {
3216 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 3211 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
3217 InstantiateBoilerplate(node->boilerplate()); 3212 InstantiateBoilerplate(node->boilerplate());
3218 } 3213 }
3219 3214
3220 3215
3221 void CodeGenerator::VisitConditional(Conditional* node) { 3216 void CodeGenerator::VisitConditional(Conditional* node) {
3222 Comment cmnt(masm_, "[ Conditional"); 3217 Comment cmnt(masm_, "[ Conditional");
3223 JumpTarget then(this); 3218 JumpTarget then;
3224 JumpTarget else_(this); 3219 JumpTarget else_;
3225 JumpTarget exit(this); 3220 JumpTarget exit;
3226 ControlDestination dest(&then, &else_, true); 3221 ControlDestination dest(&then, &else_, true);
3227 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 3222 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
3228 3223
3229 if (dest.false_was_fall_through()) { 3224 if (dest.false_was_fall_through()) {
3230 // The else target was bound, so we compile the else part first. 3225 // The else target was bound, so we compile the else part first.
3231 Load(node->else_expression(), typeof_state()); 3226 Load(node->else_expression(), typeof_state());
3232 3227
3233 if (then.is_linked()) { 3228 if (then.is_linked()) {
3234 exit.Jump(); 3229 exit.Jump();
3235 then.Bind(); 3230 then.Bind();
(...skipping 11 matching lines...) Expand all
3247 } 3242 }
3248 3243
3249 exit.Bind(); 3244 exit.Bind();
3250 } 3245 }
3251 3246
3252 3247
3253 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 3248 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
3254 if (slot->type() == Slot::LOOKUP) { 3249 if (slot->type() == Slot::LOOKUP) {
3255 ASSERT(slot->var()->is_dynamic()); 3250 ASSERT(slot->var()->is_dynamic());
3256 3251
3257 JumpTarget slow(this); 3252 JumpTarget slow;
3258 JumpTarget done(this); 3253 JumpTarget done;
3259 Result value; 3254 Result value;
3260 3255
3261 // Generate fast-case code for variables that might be shadowed by 3256 // Generate fast-case code for variables that might be shadowed by
3262 // eval-introduced variables. Eval is used a lot without 3257 // eval-introduced variables. Eval is used a lot without
3263 // introducing variables. In those cases, we do not want to 3258 // introducing variables. In those cases, we do not want to
3264 // perform a runtime call for all variables in the scope 3259 // perform a runtime call for all variables in the scope
3265 // containing the eval. 3260 // containing the eval.
3266 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { 3261 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
3267 value = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); 3262 value = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow);
3268 // If there was no control flow to slow, we can exit early. 3263 // If there was no control flow to slow, we can exit early.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3314 3309
3315 } else if (slot->var()->mode() == Variable::CONST) { 3310 } else if (slot->var()->mode() == Variable::CONST) {
3316 // Const slots may contain 'the hole' value (the constant hasn't been 3311 // Const slots may contain 'the hole' value (the constant hasn't been
3317 // initialized yet) which needs to be converted into the 'undefined' 3312 // initialized yet) which needs to be converted into the 'undefined'
3318 // value. 3313 // value.
3319 // 3314 //
3320 // We currently spill the virtual frame because constants use the 3315 // We currently spill the virtual frame because constants use the
3321 // potentially unsafe direct-frame access of SlotOperand. 3316 // potentially unsafe direct-frame access of SlotOperand.
3322 VirtualFrame::SpilledScope spilled_scope(this); 3317 VirtualFrame::SpilledScope spilled_scope(this);
3323 Comment cmnt(masm_, "[ Load const"); 3318 Comment cmnt(masm_, "[ Load const");
3324 JumpTarget exit(this); 3319 JumpTarget exit;
3325 __ mov(ecx, SlotOperand(slot, ecx)); 3320 __ mov(ecx, SlotOperand(slot, ecx));
3326 __ cmp(ecx, Factory::the_hole_value()); 3321 __ cmp(ecx, Factory::the_hole_value());
3327 exit.Branch(not_equal); 3322 exit.Branch(not_equal);
3328 __ mov(ecx, Factory::undefined_value()); 3323 __ mov(ecx, Factory::undefined_value());
3329 exit.Bind(); 3324 exit.Bind();
3330 frame_->EmitPush(ecx); 3325 frame_->EmitPush(ecx);
3331 3326
3332 } else if (slot->type() == Slot::PARAMETER) { 3327 } else if (slot->type() == Slot::PARAMETER) {
3333 frame_->PushParameterAt(slot->index()); 3328 frame_->PushParameterAt(slot->index());
3334 3329
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
3452 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3); 3447 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
3453 } 3448 }
3454 // Storing a variable must keep the (new) value on the expression 3449 // Storing a variable must keep the (new) value on the expression
3455 // stack. This is necessary for compiling chained assignment 3450 // stack. This is necessary for compiling chained assignment
3456 // expressions. 3451 // expressions.
3457 frame_->Push(&value); 3452 frame_->Push(&value);
3458 3453
3459 } else { 3454 } else {
3460 ASSERT(!slot->var()->is_dynamic()); 3455 ASSERT(!slot->var()->is_dynamic());
3461 3456
3462 JumpTarget exit(this); 3457 JumpTarget exit;
3463 if (init_state == CONST_INIT) { 3458 if (init_state == CONST_INIT) {
3464 ASSERT(slot->var()->mode() == Variable::CONST); 3459 ASSERT(slot->var()->mode() == Variable::CONST);
3465 // Only the first const initialization must be executed (the slot 3460 // Only the first const initialization must be executed (the slot
3466 // still contains 'the hole' value). When the assignment is executed, 3461 // still contains 'the hole' value). When the assignment is executed,
3467 // the code is identical to a normal store (see below). 3462 // the code is identical to a normal store (see below).
3468 // 3463 //
3469 // We spill the frame in the code below because the direct-frame 3464 // We spill the frame in the code below because the direct-frame
3470 // access of SlotOperand is potentially unsafe with an unspilled 3465 // access of SlotOperand is potentially unsafe with an unspilled
3471 // frame. 3466 // frame.
3472 VirtualFrame::SpilledScope spilled_scope(this); 3467 VirtualFrame::SpilledScope spilled_scope(this);
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after
4277 4272
4278 // This generates code that performs a charCodeAt() call or returns 4273 // This generates code that performs a charCodeAt() call or returns
4279 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 4274 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
4280 // It can handle flat and sliced strings, 8 and 16 bit characters and 4275 // It can handle flat and sliced strings, 8 and 16 bit characters and
4281 // cons strings where the answer is found in the left hand branch of the 4276 // cons strings where the answer is found in the left hand branch of the
4282 // cons. The slow case will flatten the string, which will ensure that 4277 // cons. The slow case will flatten the string, which will ensure that
4283 // the answer is in the left hand side the next time around. 4278 // the answer is in the left hand side the next time around.
4284 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 4279 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
4285 ASSERT(args->length() == 2); 4280 ASSERT(args->length() == 2);
4286 4281
4287 JumpTarget slow_case(this); 4282 JumpTarget slow_case;
4288 JumpTarget end(this); 4283 JumpTarget end;
4289 JumpTarget not_a_flat_string(this); 4284 JumpTarget not_a_flat_string;
4290 JumpTarget a_cons_string(this); 4285 JumpTarget a_cons_string;
4291 JumpTarget try_again_with_new_string(this, JumpTarget::BIDIRECTIONAL); 4286 JumpTarget try_again_with_new_string(JumpTarget::BIDIRECTIONAL);
4292 JumpTarget ascii_string(this); 4287 JumpTarget ascii_string;
4293 JumpTarget got_char_code(this); 4288 JumpTarget got_char_code;
4294 4289
4295 Load(args->at(0)); 4290 Load(args->at(0));
4296 Load(args->at(1)); 4291 Load(args->at(1));
4297 // Reserve register ecx, to use as shift amount later 4292 // Reserve register ecx, to use as shift amount later
4298 Result shift_amount = allocator()->Allocate(ecx); 4293 Result shift_amount = allocator()->Allocate(ecx);
4299 ASSERT(shift_amount.is_valid()); 4294 ASSERT(shift_amount.is_valid());
4300 Result index = frame_->Pop(); 4295 Result index = frame_->Pop();
4301 index.ToRegister(); 4296 index.ToRegister();
4302 Result object = frame_->Pop(); 4297 Result object = frame_->Pop();
4303 object.ToRegister(); 4298 object.ToRegister();
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
4441 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters()))); 4436 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
4442 // Call the shared stub to get to the arguments.length. 4437 // Call the shared stub to get to the arguments.length.
4443 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); 4438 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
4444 Result result = frame_->CallStub(&stub, &count); 4439 Result result = frame_->CallStub(&stub, &count);
4445 frame_->Push(&result); 4440 frame_->Push(&result);
4446 } 4441 }
4447 4442
4448 4443
4449 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 4444 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
4450 ASSERT(args->length() == 1); 4445 ASSERT(args->length() == 1);
4451 JumpTarget leave(this); 4446 JumpTarget leave;
4452 Load(args->at(0)); // Load the object. 4447 Load(args->at(0)); // Load the object.
4453 frame_->Dup(); 4448 frame_->Dup();
4454 Result object = frame_->Pop(); 4449 Result object = frame_->Pop();
4455 object.ToRegister(); 4450 object.ToRegister();
4456 ASSERT(object.is_valid()); 4451 ASSERT(object.is_valid());
4457 // if (object->IsSmi()) return object. 4452 // if (object->IsSmi()) return object.
4458 __ test(object.reg(), Immediate(kSmiTagMask)); 4453 __ test(object.reg(), Immediate(kSmiTagMask));
4459 leave.Branch(zero, taken); 4454 leave.Branch(zero, taken);
4460 // It is a heap object - get map. 4455 // It is a heap object - get map.
4461 Result temp = allocator()->Allocate(); 4456 Result temp = allocator()->Allocate();
4462 ASSERT(temp.is_valid()); 4457 ASSERT(temp.is_valid());
4463 // if (!object->IsJSValue()) return object. 4458 // if (!object->IsJSValue()) return object.
4464 __ CmpObjectType(object.reg(), JS_VALUE_TYPE, temp.reg()); 4459 __ CmpObjectType(object.reg(), JS_VALUE_TYPE, temp.reg());
4465 leave.Branch(not_equal, not_taken); 4460 leave.Branch(not_equal, not_taken);
4466 __ mov(temp.reg(), FieldOperand(object.reg(), JSValue::kValueOffset)); 4461 __ mov(temp.reg(), FieldOperand(object.reg(), JSValue::kValueOffset));
4467 object.Unuse(); 4462 object.Unuse();
4468 frame_->SetElementAt(0, &temp); 4463 frame_->SetElementAt(0, &temp);
4469 leave.Bind(); 4464 leave.Bind();
4470 } 4465 }
4471 4466
4472 4467
4473 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 4468 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
4474 ASSERT(args->length() == 2); 4469 ASSERT(args->length() == 2);
4475 JumpTarget leave(this); 4470 JumpTarget leave;
4476 Load(args->at(0)); // Load the object. 4471 Load(args->at(0)); // Load the object.
4477 Load(args->at(1)); // Load the value. 4472 Load(args->at(1)); // Load the value.
4478 Result value = frame_->Pop(); 4473 Result value = frame_->Pop();
4479 Result object = frame_->Pop(); 4474 Result object = frame_->Pop();
4480 value.ToRegister(); 4475 value.ToRegister();
4481 object.ToRegister(); 4476 object.ToRegister();
4482 4477
4483 // if (object->IsSmi()) return value. 4478 // if (object->IsSmi()) return value.
4484 __ test(object.reg(), Immediate(kSmiTagMask)); 4479 __ test(object.reg(), Immediate(kSmiTagMask));
4485 leave.Branch(zero, &value, taken); 4480 leave.Branch(zero, &value, taken);
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
4694 UnarySubStub stub; 4689 UnarySubStub stub;
4695 // TODO(1222589): remove dependency of TOS being cached inside stub 4690 // TODO(1222589): remove dependency of TOS being cached inside stub
4696 Result operand = frame_->Pop(); 4691 Result operand = frame_->Pop();
4697 Result answer = frame_->CallStub(&stub, &operand); 4692 Result answer = frame_->CallStub(&stub, &operand);
4698 frame_->Push(&answer); 4693 frame_->Push(&answer);
4699 break; 4694 break;
4700 } 4695 }
4701 4696
4702 case Token::BIT_NOT: { 4697 case Token::BIT_NOT: {
4703 // Smi check. 4698 // Smi check.
4704 JumpTarget smi_label(this); 4699 JumpTarget smi_label;
4705 JumpTarget continue_label(this); 4700 JumpTarget continue_label;
4706 Result operand = frame_->Pop(); 4701 Result operand = frame_->Pop();
4707 operand.ToRegister(); 4702 operand.ToRegister();
4708 __ test(operand.reg(), Immediate(kSmiTagMask)); 4703 __ test(operand.reg(), Immediate(kSmiTagMask));
4709 smi_label.Branch(zero, &operand, taken); 4704 smi_label.Branch(zero, &operand, taken);
4710 4705
4711 frame_->Push(&operand); // undo popping of TOS 4706 frame_->Push(&operand); // undo popping of TOS
4712 Result answer = frame_->InvokeBuiltin(Builtins::BIT_NOT, 4707 Result answer = frame_->InvokeBuiltin(Builtins::BIT_NOT,
4713 CALL_FUNCTION, 1); 4708 CALL_FUNCTION, 1);
4714 4709
4715 continue_label.Jump(&answer); 4710 continue_label.Jump(&answer);
4716 smi_label.Bind(&answer); 4711 smi_label.Bind(&answer);
4717 answer.ToRegister(); 4712 answer.ToRegister();
4718 frame_->Spill(answer.reg()); 4713 frame_->Spill(answer.reg());
4719 __ not_(answer.reg()); 4714 __ not_(answer.reg());
4720 __ and_(answer.reg(), ~kSmiTagMask); // Remove inverted smi-tag. 4715 __ and_(answer.reg(), ~kSmiTagMask); // Remove inverted smi-tag.
4721 continue_label.Bind(&answer); 4716 continue_label.Bind(&answer);
4722 frame_->Push(&answer); 4717 frame_->Push(&answer);
4723 break; 4718 break;
4724 } 4719 }
4725 4720
4726 case Token::ADD: { 4721 case Token::ADD: {
4727 // Smi check. 4722 // Smi check.
4728 JumpTarget continue_label(this); 4723 JumpTarget continue_label;
4729 Result operand = frame_->Pop(); 4724 Result operand = frame_->Pop();
4730 operand.ToRegister(); 4725 operand.ToRegister();
4731 __ test(operand.reg(), Immediate(kSmiTagMask)); 4726 __ test(operand.reg(), Immediate(kSmiTagMask));
4732 continue_label.Branch(zero, &operand, taken); 4727 continue_label.Branch(zero, &operand, taken);
4733 4728
4734 frame_->Push(&operand); 4729 frame_->Push(&operand);
4735 Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER, 4730 Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER,
4736 CALL_FUNCTION, 1); 4731 CALL_FUNCTION, 1);
4737 4732
4738 continue_label.Bind(&answer); 4733 continue_label.Bind(&answer);
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
4913 // According to ECMA-262 section 11.11, page 58, the binary logical 4908 // According to ECMA-262 section 11.11, page 58, the binary logical
4914 // operators must yield the result of one of the two expressions 4909 // operators must yield the result of one of the two expressions
4915 // before any ToBoolean() conversions. This means that the value 4910 // before any ToBoolean() conversions. This means that the value
4916 // produced by a && or || operator is not necessarily a boolean. 4911 // produced by a && or || operator is not necessarily a boolean.
4917 4912
4918 // NOTE: If the left hand side produces a materialized value (not 4913 // NOTE: If the left hand side produces a materialized value (not
4919 // control flow), we force the right hand side to do the same. This 4914 // control flow), we force the right hand side to do the same. This
4920 // is necessary because we assume that if we get control flow on the 4915 // is necessary because we assume that if we get control flow on the
4921 // last path out of an expression we got it on all paths. 4916 // last path out of an expression we got it on all paths.
4922 if (op == Token::AND) { 4917 if (op == Token::AND) {
4923 JumpTarget is_true(this); 4918 JumpTarget is_true;
4924 ControlDestination dest(&is_true, destination()->false_target(), true); 4919 ControlDestination dest(&is_true, destination()->false_target(), true);
4925 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false); 4920 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false);
4926 4921
4927 if (dest.false_was_fall_through()) { 4922 if (dest.false_was_fall_through()) {
4928 // The current false target was used as the fall-through. If 4923 // The current false target was used as the fall-through. If
4929 // there are no dangling jumps to is_true then the left 4924 // there are no dangling jumps to is_true then the left
4930 // subexpression was unconditionally false. Otherwise we have 4925 // subexpression was unconditionally false. Otherwise we have
4931 // paths where we do have to evaluate the right subexpression. 4926 // paths where we do have to evaluate the right subexpression.
4932 if (is_true.is_linked()) { 4927 if (is_true.is_linked()) {
4933 // We need to compile the right subexpression. If the jump to 4928 // We need to compile the right subexpression. If the jump to
(...skipping 17 matching lines...) Expand all
4951 4946
4952 } else if (dest.is_used()) { 4947 } else if (dest.is_used()) {
4953 // The left subexpression compiled to control flow (and is_true 4948 // The left subexpression compiled to control flow (and is_true
4954 // was just bound), so the right is free to do so as well. 4949 // was just bound), so the right is free to do so as well.
4955 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); 4950 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false);
4956 4951
4957 } else { 4952 } else {
4958 // We have a materialized value on the frame, so we exit with 4953 // We have a materialized value on the frame, so we exit with
4959 // one on all paths. There are possibly also jumps to is_true 4954 // one on all paths. There are possibly also jumps to is_true
4960 // from nested subexpressions. 4955 // from nested subexpressions.
4961 JumpTarget pop_and_continue(this); 4956 JumpTarget pop_and_continue;
4962 JumpTarget exit(this); 4957 JumpTarget exit;
4963 4958
4964 // Avoid popping the result if it converts to 'false' using the 4959 // Avoid popping the result if it converts to 'false' using the
4965 // standard ToBoolean() conversion as described in ECMA-262, 4960 // standard ToBoolean() conversion as described in ECMA-262,
4966 // section 9.2, page 30. 4961 // section 9.2, page 30.
4967 // 4962 //
4968 // Duplicate the TOS value. The duplicate will be popped by 4963 // Duplicate the TOS value. The duplicate will be popped by
4969 // ToBoolean. 4964 // ToBoolean.
4970 frame_->Dup(); 4965 frame_->Dup();
4971 ControlDestination dest(&pop_and_continue, &exit, true); 4966 ControlDestination dest(&pop_and_continue, &exit, true);
4972 ToBoolean(&dest); 4967 ToBoolean(&dest);
4973 4968
4974 // Pop the result of evaluating the first part. 4969 // Pop the result of evaluating the first part.
4975 frame_->Drop(); 4970 frame_->Drop();
4976 4971
4977 // Compile right side expression. 4972 // Compile right side expression.
4978 is_true.Bind(); 4973 is_true.Bind();
4979 Load(node->right()); 4974 Load(node->right());
4980 4975
4981 // Exit (always with a materialized value). 4976 // Exit (always with a materialized value).
4982 exit.Bind(); 4977 exit.Bind();
4983 } 4978 }
4984 4979
4985 } else if (op == Token::OR) { 4980 } else if (op == Token::OR) {
4986 JumpTarget is_false(this); 4981 JumpTarget is_false;
4987 ControlDestination dest(destination()->true_target(), &is_false, false); 4982 ControlDestination dest(destination()->true_target(), &is_false, false);
4988 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false); 4983 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false);
4989 4984
4990 if (dest.true_was_fall_through()) { 4985 if (dest.true_was_fall_through()) {
4991 // The current true target was used as the fall-through. If 4986 // The current true target was used as the fall-through. If
4992 // there are no dangling jumps to is_false then the left 4987 // there are no dangling jumps to is_false then the left
4993 // subexpression was unconditionally true. Otherwise we have 4988 // subexpression was unconditionally true. Otherwise we have
4994 // paths where we do have to evaluate the right subexpression. 4989 // paths where we do have to evaluate the right subexpression.
4995 if (is_false.is_linked()) { 4990 if (is_false.is_linked()) {
4996 // We need to compile the right subexpression. If the jump to 4991 // We need to compile the right subexpression. If the jump to
(...skipping 16 matching lines...) Expand all
5013 5008
5014 } else if (dest.is_used()) { 5009 } else if (dest.is_used()) {
5015 // The left subexpression compiled to control flow (and is_false 5010 // The left subexpression compiled to control flow (and is_false
5016 // was just bound), so the right is free to do so as well. 5011 // was just bound), so the right is free to do so as well.
5017 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); 5012 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false);
5018 5013
5019 } else { 5014 } else {
5020 // We have a materialized value on the frame, so we exit with 5015 // We have a materialized value on the frame, so we exit with
5021 // one on all paths. There are possibly also jumps to is_false 5016 // one on all paths. There are possibly also jumps to is_false
5022 // from nested subexpressions. 5017 // from nested subexpressions.
5023 JumpTarget pop_and_continue(this); 5018 JumpTarget pop_and_continue;
5024 JumpTarget exit(this); 5019 JumpTarget exit;
5025 5020
5026 // Avoid popping the result if it converts to 'true' using the 5021 // Avoid popping the result if it converts to 'true' using the
5027 // standard ToBoolean() conversion as described in ECMA-262, 5022 // standard ToBoolean() conversion as described in ECMA-262,
5028 // section 9.2, page 30. 5023 // section 9.2, page 30.
5029 // 5024 //
5030 // Duplicate the TOS value. The duplicate will be popped by 5025 // Duplicate the TOS value. The duplicate will be popped by
5031 // ToBoolean. 5026 // ToBoolean.
5032 frame_->Dup(); 5027 frame_->Dup();
5033 ControlDestination dest(&exit, &pop_and_continue, false); 5028 ControlDestination dest(&exit, &pop_and_continue, false);
5034 ToBoolean(&dest); 5029 ToBoolean(&dest);
(...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after
5968 // Check that the *unsigned* result fits in a smi. 5963 // Check that the *unsigned* result fits in a smi.
5969 // Neither of the two high-order bits can be set: 5964 // Neither of the two high-order bits can be set:
5970 // - 0x80000000: high bit would be lost when smi tagging. 5965 // - 0x80000000: high bit would be lost when smi tagging.
5971 // - 0x40000000: this number would convert to negative when 5966 // - 0x40000000: this number would convert to negative when
5972 // Smi tagging these two cases can only happen with shifts 5967 // Smi tagging these two cases can only happen with shifts
5973 // by 0 or 1 when handed a valid smi. 5968 // by 0 or 1 when handed a valid smi.
5974 // If the answer cannot be represented by a SMI, restore 5969 // If the answer cannot be represented by a SMI, restore
5975 // the left and right arguments, and jump to slow case. 5970 // the left and right arguments, and jump to slow case.
5976 // The low bit of the left argument may be lost, but only 5971 // The low bit of the left argument may be lost, but only
5977 // in a case where it is dropped anyway. 5972 // in a case where it is dropped anyway.
5978 JumpTarget result_ok(generator()); 5973 JumpTarget result_ok;
5979 __ test(left->reg(), Immediate(0xc0000000)); 5974 __ test(left->reg(), Immediate(0xc0000000));
5980 result_ok.Branch(zero, left, taken); 5975 result_ok.Branch(zero, left, taken);
5981 __ shl(left->reg()); 5976 __ shl(left->reg());
5982 ASSERT(kSmiTag == 0); 5977 ASSERT(kSmiTag == 0);
5983 __ shl(left->reg(), kSmiTagSize); 5978 __ shl(left->reg(), kSmiTagSize);
5984 __ shl(right->reg(), kSmiTagSize); 5979 __ shl(right->reg(), kSmiTagSize);
5985 enter()->Jump(left, right); 5980 enter()->Jump(left, right);
5986 result_ok.Bind(left); 5981 result_ok.Bind(left);
5987 break; 5982 break;
5988 } 5983 }
5989 case Token::SHL: { 5984 case Token::SHL: {
5990 __ shl(left->reg()); 5985 __ shl(left->reg());
5991 // Check that the *signed* result fits in a smi. 5986 // Check that the *signed* result fits in a smi.
5992 JumpTarget result_ok(generator()); 5987 JumpTarget result_ok;
5993 __ cmp(left->reg(), 0xc0000000); 5988 __ cmp(left->reg(), 0xc0000000);
5994 result_ok.Branch(positive, left, taken); 5989 result_ok.Branch(positive, left, taken);
5995 5990
5996 __ shr(left->reg()); 5991 __ shr(left->reg());
5997 ASSERT(kSmiTag == 0); 5992 ASSERT(kSmiTag == 0);
5998 __ shl(left->reg(), kSmiTagSize); 5993 __ shl(left->reg(), kSmiTagSize);
5999 __ shl(right->reg(), kSmiTagSize); 5994 __ shl(right->reg(), kSmiTagSize);
6000 enter()->Jump(left, right); 5995 enter()->Jump(left, right);
6001 result_ok.Bind(left); 5996 result_ok.Bind(left);
6002 break; 5997 break;
(...skipping 1235 matching lines...) Expand 10 before | Expand all | Expand 10 after
7238 7233
7239 // Slow-case: Go through the JavaScript implementation. 7234 // Slow-case: Go through the JavaScript implementation.
7240 __ bind(&slow); 7235 __ bind(&slow);
7241 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 7236 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
7242 } 7237 }
7243 7238
7244 7239
7245 #undef __ 7240 #undef __
7246 7241
7247 } } // namespace v8::internal 7242 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen.cc ('k') | src/ia32/jump-target-ia32.cc » ('j') | src/jump-target.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698