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

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

Issue 10829: Finish porting jump target changes to the ARM platform. The v8 test... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 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/codegen-arm.cc ('k') | src/jump-target-arm.cc » ('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-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 for (int i = 0; i < scope_->num_parameters(); i++) { 199 for (int i = 0; i < scope_->num_parameters(); i++) {
200 Variable* par = scope_->parameter(i); 200 Variable* par = scope_->parameter(i);
201 Slot* slot = par->slot(); 201 Slot* slot = par->slot();
202 if (slot != NULL && slot->type() == Slot::CONTEXT) { 202 if (slot != NULL && slot->type() == Slot::CONTEXT) {
203 // Save the arguments object pointer, if any. 203 // Save the arguments object pointer, if any.
204 if (arguments_object_allocated && !arguments_object_saved) { 204 if (arguments_object_allocated && !arguments_object_saved) {
205 frame_->Push(ecx); 205 frame_->Push(ecx);
206 arguments_object_saved = true; 206 arguments_object_saved = true;
207 } 207 }
208 ASSERT(!scope_->is_global_scope()); // no parameters in global scope 208 ASSERT(!scope_->is_global_scope()); // no parameters in global scope
209 __ mov(eax, frame_->Parameter(i)); 209 __ mov(eax, frame_->ParameterAt(i));
210 // Loads ecx with context; used below in RecordWrite. 210 // Loads ecx with context; used below in RecordWrite.
211 __ mov(SlotOperand(slot, ecx), eax); 211 __ mov(SlotOperand(slot, ecx), eax);
212 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 212 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
213 __ RecordWrite(ecx, offset, eax, ebx); 213 __ RecordWrite(ecx, offset, eax, ebx);
214 } 214 }
215 } 215 }
216 } 216 }
217 217
218 // This section stores the pointer to the arguments object that 218 // This section stores the pointer to the arguments object that
219 // was allocated and copied into above. If the address was not 219 // was allocated and copied into above. If the address was not
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 // (such as the variable referring to a named function expression). 313 // (such as the variable referring to a named function expression).
314 // We need to implement assignments to read-only variables. 314 // We need to implement assignments to read-only variables.
315 // Ideally, we should do this during AST generation (by converting 315 // Ideally, we should do this during AST generation (by converting
316 // such assignments into expression statements); however, in general 316 // such assignments into expression statements); however, in general
317 // we may not be able to make the decision until past AST generation, 317 // we may not be able to make the decision until past AST generation,
318 // that is when the entire program is known. 318 // that is when the entire program is known.
319 ASSERT(slot != NULL); 319 ASSERT(slot != NULL);
320 int index = slot->index(); 320 int index = slot->index();
321 switch (slot->type()) { 321 switch (slot->type()) {
322 case Slot::PARAMETER: 322 case Slot::PARAMETER:
323 return frame_->Parameter(index); 323 return frame_->ParameterAt(index);
324 324
325 case Slot::LOCAL: 325 case Slot::LOCAL:
326 return frame_->Local(index); 326 return frame_->LocalAt(index);
327 327
328 case Slot::CONTEXT: { 328 case Slot::CONTEXT: {
329 // Follow the context chain if necessary. 329 // Follow the context chain if necessary.
330 ASSERT(!tmp.is(esi)); // do not overwrite context register 330 ASSERT(!tmp.is(esi)); // do not overwrite context register
331 Register context = esi; 331 Register context = esi;
332 int chain_length = scope()->ContextChainLength(slot->var()->scope()); 332 int chain_length = scope()->ContextChainLength(slot->var()->scope());
333 for (int i = chain_length; i-- > 0;) { 333 for (int i = chain_length; i-- > 0;) {
334 // Load the closure. 334 // Load the closure.
335 // (All contexts, even 'with' contexts, have a closure, 335 // (All contexts, even 'with' contexts, have a closure,
336 // and it is the same for all contexts inside a function. 336 // and it is the same for all contexts inside a function.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 JumpTarget* false_target, 370 JumpTarget* false_target,
371 bool force_cc) { 371 bool force_cc) {
372 ASSERT(!has_cc()); 372 ASSERT(!has_cc());
373 373
374 { CodeGenState new_state(this, typeof_state, true_target, false_target); 374 { CodeGenState new_state(this, typeof_state, true_target, false_target);
375 Visit(x); 375 Visit(x);
376 } 376 }
377 377
378 if (force_cc && frame_ != NULL && !has_cc()) { 378 if (force_cc && frame_ != NULL && !has_cc()) {
379 // Convert the TOS value to a boolean in the condition code register. 379 // Convert the TOS value to a boolean in the condition code register.
380 // Visiting an expression may possibly choose neither (a) to leave a
381 // value in the condition code register nor (b) to leave a value in TOS
382 // (eg, by compiling to only jumps to the targets). In that case the
383 // code generated by ToBoolean is wrong because it assumes the value of
384 // the expression in TOS. So long as there is always a value in TOS or
385 // the condition code register when control falls through to here (there
386 // is), the code generated by ToBoolean is dead and therefore safe.
387 ToBoolean(true_target, false_target); 380 ToBoolean(true_target, false_target);
388 } 381 }
389 382
390 ASSERT(!force_cc || frame_ == NULL || has_cc()); 383 ASSERT(!force_cc || frame_ == NULL || has_cc());
391 } 384 }
392 385
393 386
394 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 387 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
395 JumpTarget true_target(this); 388 JumpTarget true_target(this);
396 JumpTarget false_target(this); 389 JumpTarget false_target(this);
397 LoadCondition(x, typeof_state, &true_target, &false_target, false); 390 LoadCondition(x, typeof_state, &true_target, &false_target, false);
398 391
399 if (has_cc()) { 392 if (has_cc()) {
400 ASSERT(frame_ != NULL); 393 ASSERT(frame_ != NULL);
401 // convert cc_reg_ into a bool 394 // Convert cc_reg_ into a boolean value.
402 JumpTarget loaded(this); 395 JumpTarget loaded(this);
403 JumpTarget materialize_true(this); 396 JumpTarget materialize_true(this);
404 materialize_true.Branch(cc_reg_); 397 materialize_true.Branch(cc_reg_);
405 frame_->Push(Immediate(Factory::false_value())); 398 frame_->Push(Immediate(Factory::false_value()));
406 loaded.Jump(); 399 loaded.Jump();
407 materialize_true.Bind(); 400 materialize_true.Bind();
408 frame_->Push(Immediate(Factory::true_value())); 401 frame_->Push(Immediate(Factory::true_value()));
409 loaded.Bind(); 402 loaded.Bind();
410 cc_reg_ = no_condition; 403 cc_reg_ = no_condition;
411 } 404 }
412 405
413 if (true_target.is_linked() || false_target.is_linked()) { 406 if (true_target.is_linked() || false_target.is_linked()) {
414 // we have at least one condition value 407 // We have at least one condition value that has been "translated" into
415 // that has been "translated" into a branch, 408 // a branch, thus it needs to be loaded explicitly.
416 // thus it needs to be loaded explicitly again
417 JumpTarget loaded(this); 409 JumpTarget loaded(this);
418 if (frame_ != NULL) { 410 if (frame_ != NULL) {
419 loaded.Jump(); // don't lose current TOS 411 loaded.Jump(); // Don't lose the current TOS.
420 } 412 }
421 bool both = true_target.is_linked() && false_target.is_linked(); 413 bool both = true_target.is_linked() && false_target.is_linked();
422 // reincarnate "true", if necessary 414 // Load "true" if necessary.
423 if (true_target.is_linked()) { 415 if (true_target.is_linked()) {
424 true_target.Bind(); 416 true_target.Bind();
425 frame_->Push(Immediate(Factory::true_value())); 417 frame_->Push(Immediate(Factory::true_value()));
426 } 418 }
427 // if both "true" and "false" need to be reincarnated, 419 // If both "true" and "false" need to be reincarnated jump across the
428 // jump across code for "false" 420 // code for "false".
429 if (both) { 421 if (both) {
430 loaded.Jump(); 422 loaded.Jump();
431 } 423 }
432 // reincarnate "false", if necessary 424 // Load "false" if necessary.
433 if (false_target.is_linked()) { 425 if (false_target.is_linked()) {
434 false_target.Bind(); 426 false_target.Bind();
435 frame_->Push(Immediate(Factory::false_value())); 427 frame_->Push(Immediate(Factory::false_value()));
436 } 428 }
437 // everything is loaded at this point 429 // A value is loaded on all paths reaching this point.
438 loaded.Bind(); 430 loaded.Bind();
439 } 431 }
432 ASSERT(frame_ != NULL);
440 ASSERT(!has_cc()); 433 ASSERT(!has_cc());
441 } 434 }
442 435
443 436
444 void CodeGenerator::LoadGlobal() { 437 void CodeGenerator::LoadGlobal() {
445 frame_->Push(GlobalObject()); 438 frame_->Push(GlobalObject());
446 } 439 }
447 440
448 441
449 void CodeGenerator::LoadGlobalReceiver(Register scratch) { 442 void CodeGenerator::LoadGlobalReceiver(Register scratch) {
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 Major MajorKey() { return CallFunction; } 1226 Major MajorKey() { return CallFunction; }
1234 int MinorKey() { return argc_; } 1227 int MinorKey() { return argc_; }
1235 }; 1228 };
1236 1229
1237 1230
1238 // Call the function just below TOS on the stack with the given 1231 // Call the function just below TOS on the stack with the given
1239 // arguments. The receiver is the TOS. 1232 // arguments. The receiver is the TOS.
1240 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 1233 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
1241 int position) { 1234 int position) {
1242 // Push the arguments ("left-to-right") on the stack. 1235 // Push the arguments ("left-to-right") on the stack.
1243 for (int i = 0; i < args->length(); i++) { 1236 int arg_count = args->length();
1237 for (int i = 0; i < arg_count; i++) {
1244 Load(args->at(i)); 1238 Load(args->at(i));
1245 } 1239 }
1246 1240
1247 // Record the position for debugging purposes. 1241 // Record the position for debugging purposes.
1248 __ RecordPosition(position); 1242 __ RecordPosition(position);
1249 1243
1250 // Use the shared code stub to call the function. 1244 // Use the shared code stub to call the function.
1251 CallFunctionStub call_function(args->length()); 1245 CallFunctionStub call_function(arg_count);
1252 frame_->CallStub(&call_function, args->length() + 1); 1246 frame_->CallStub(&call_function, arg_count + 1);
1253 1247
1254 // Restore context and pop function from the stack. 1248 // Restore context and pop function from the stack.
1255 __ mov(esi, frame_->Context()); 1249 __ mov(esi, frame_->Context());
1256 __ mov(frame_->Top(), eax); 1250 __ mov(frame_->Top(), eax);
1257 } 1251 }
1258 1252
1259 1253
1260 void CodeGenerator::Branch(bool if_true, JumpTarget* target) { 1254 void CodeGenerator::Branch(bool if_true, JumpTarget* target) {
1261 ASSERT(has_cc()); 1255 ASSERT(has_cc());
1262 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); 1256 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 1374
1381 1375
1382 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { 1376 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
1383 Comment cmnt(masm_, "// EmptyStatement"); 1377 Comment cmnt(masm_, "// EmptyStatement");
1384 // nothing to do 1378 // nothing to do
1385 } 1379 }
1386 1380
1387 1381
1388 void CodeGenerator::VisitIfStatement(IfStatement* node) { 1382 void CodeGenerator::VisitIfStatement(IfStatement* node) {
1389 Comment cmnt(masm_, "[ IfStatement"); 1383 Comment cmnt(masm_, "[ IfStatement");
1390 // Generate different code depending on which 1384 // Generate different code depending on which parts of the if statement
1391 // parts of the if statement are present or not. 1385 // are present or not.
1392 bool has_then_stm = node->HasThenStatement(); 1386 bool has_then_stm = node->HasThenStatement();
1393 bool has_else_stm = node->HasElseStatement(); 1387 bool has_else_stm = node->HasElseStatement();
1394 1388
1395 RecordStatementPosition(node); 1389 RecordStatementPosition(node);
1396 JumpTarget exit(this); 1390 JumpTarget exit(this);
1397 if (has_then_stm && has_else_stm) { 1391 if (has_then_stm && has_else_stm) {
1398 JumpTarget then(this); 1392 JumpTarget then(this);
1399 JumpTarget else_(this); 1393 JumpTarget else_(this);
1400 // if (cond) 1394 // if (cond)
1401 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); 1395 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1652 Load(node->tag()); 1646 Load(node->tag());
1653 1647
1654 if (TryGenerateFastCaseSwitchStatement(node)) { 1648 if (TryGenerateFastCaseSwitchStatement(node)) {
1655 return; 1649 return;
1656 } 1650 }
1657 1651
1658 JumpTarget next_test(this); 1652 JumpTarget next_test(this);
1659 JumpTarget fall_through(this); 1653 JumpTarget fall_through(this);
1660 JumpTarget default_entry(this); 1654 JumpTarget default_entry(this);
1661 JumpTarget default_exit(this); 1655 JumpTarget default_exit(this);
1662
1663 ZoneList<CaseClause*>* cases = node->cases(); 1656 ZoneList<CaseClause*>* cases = node->cases();
1664 int length = cases->length(); 1657 int length = cases->length();
1665 CaseClause* default_clause = NULL; 1658 CaseClause* default_clause = NULL;
1666 1659
1667 for (int i = 0; i < length; i++) { 1660 for (int i = 0; i < length; i++) {
1668 CaseClause* clause = cases->at(i); 1661 CaseClause* clause = cases->at(i);
1662 if (clause->is_default()) {
1663 // Remember the default clause and compile it at the end.
1664 default_clause = clause;
1665 continue;
1666 }
1669 1667
1670 if (clause->is_default()) { 1668 Comment cmnt(masm_, "[ Case clause");
1671 default_clause = clause; 1669 // Compile the test.
1670 next_test.Bind();
1671 next_test.Unuse();
1672 // Duplicate TOS.
1673 __ mov(eax, frame_->Top());
1674 frame_->Push(eax);
1675 Load(clause->label());
1676 Comparison(equal, true);
1677 Branch(false, &next_test);
1678
1679 // Before entering the body from the test, remove the switch value from
1680 // the stack.
1681 frame_->Drop();
1682
1683 // Label the body so that fall through is enabled.
1684 if (i > 0 && cases->at(i - 1)->is_default()) {
1685 default_exit.Bind();
1672 } else { 1686 } else {
1673 Comment cmnt(masm_, "[ Case clause"); 1687 fall_through.Bind();
1688 fall_through.Unuse();
1689 }
1690 VisitStatements(clause->statements());
1674 1691
1675 // Compile the test. 1692 // If control flow can fall through from the body, jump to the next body
1676 next_test.Bind(); 1693 // or the end of the statement.
1677 next_test.Unuse(); 1694 if (frame_ != NULL) {
1678 // Duplicate TOS. 1695 if (i < length - 1 && cases->at(i + 1)->is_default()) {
1679 __ mov(eax, frame_->Top()); 1696 default_entry.Jump();
1680 frame_->Push(eax);
1681 Load(clause->label());
1682 Comparison(equal, true);
1683 Branch(false, &next_test);
1684
1685 // Before entering the body, remove the switch value from the stack.
1686 frame_->Drop();
1687
1688 // Label the body so that fall through is enabled.
1689 if (i > 0 && cases->at(i - 1)->is_default()) {
1690 default_exit.Bind();
1691 } else { 1697 } else {
1692 fall_through.Bind(); 1698 fall_through.Jump();
1693 fall_through.Unuse();
1694 }
1695 VisitStatements(clause->statements());
1696
1697 // If control flow can fall through from the body jump to the
1698 // next body or end of the statement.
1699 if (frame_ != NULL) {
1700 if (i < length - 1 && cases->at(i + 1)->is_default()) {
1701 default_entry.Jump();
1702 } else {
1703 fall_through.Jump();
1704 }
1705 } 1699 }
1706 } 1700 }
1707 } 1701 }
1708 1702
1709 // The final test removes the switch value. 1703 // The final "test" removes the switch value.
1710 next_test.Bind(); 1704 next_test.Bind();
1711 frame_->Drop(); 1705 frame_->Drop();
1712 1706
1713 // If there is a default clause, compile it. 1707 // If there is a default clause, compile it.
1714 if (default_clause != NULL) { 1708 if (default_clause != NULL) {
1715 Comment cmnt(masm_, "[ Default clause"); 1709 Comment cmnt(masm_, "[ Default clause");
1716 default_entry.Bind(); 1710 default_entry.Bind();
1717 VisitStatements(default_clause->statements()); 1711 VisitStatements(default_clause->statements());
1718 // If control flow can fall out of the default and there is a case after 1712 // If control flow can fall out of the default and there is a case after
1719 // it, jump to that case's body. 1713 // it, jump to that case's body.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1752 info = ALWAYS_TRUE; 1746 info = ALWAYS_TRUE;
1753 } else if (lit->IsFalse()) { 1747 } else if (lit->IsFalse()) {
1754 info = ALWAYS_FALSE; 1748 info = ALWAYS_FALSE;
1755 } 1749 }
1756 } 1750 }
1757 } 1751 }
1758 1752
1759 switch (node->type()) { 1753 switch (node->type()) {
1760 case LoopStatement::DO_LOOP: { 1754 case LoopStatement::DO_LOOP: {
1761 JumpTarget body(this); 1755 JumpTarget body(this);
1762
1763 IncrementLoopNesting(); 1756 IncrementLoopNesting();
1764 // Label the body. 1757 // Label the body.
1765 if (info == ALWAYS_TRUE) { 1758 if (info == ALWAYS_TRUE) {
1766 node->continue_target()->Bind(); 1759 node->continue_target()->Bind();
1767 } else if (info == ALWAYS_FALSE) { 1760 } else if (info == ALWAYS_FALSE) {
1768 // There is no need, we will never jump back. 1761 // There is no need, we will never jump back.
1769 } else { 1762 } else {
1770 ASSERT(info == DONT_KNOW); 1763 ASSERT(info == DONT_KNOW);
1771 body.Bind(); 1764 body.Bind();
1772 } 1765 }
1773 CheckStack(); // TODO(1222600): ignore if body contains calls. 1766 CheckStack(); // TODO(1222600): ignore if body contains calls.
1774 Visit(node->body()); 1767 Visit(node->body());
1775 1768
1769 // Compile the "test".
1776 if (info == ALWAYS_TRUE) { 1770 if (info == ALWAYS_TRUE) {
1777 if (frame_ != NULL) { 1771 if (frame_ != NULL) {
1778 // If control flow can fall off the end of the body, jump back to 1772 // If control flow can fall off the end of the body, jump back to
1779 // the top. 1773 // the top.
1780 node->continue_target()->Jump(); 1774 node->continue_target()->Jump();
1781 } 1775 }
1782 } else if (info == ALWAYS_FALSE) { 1776 } else if (info == ALWAYS_FALSE) {
1783 // If we have a continue in the body, we only have to bind its jump 1777 // If we have a continue in the body, we only have to bind its jump
1784 // target. 1778 // target.
1785 if (node->continue_target()->is_linked()) { 1779 if (node->continue_target()->is_linked()) {
1786 node->continue_target()->Bind(); 1780 node->continue_target()->Bind();
1787 } 1781 }
1788 } else { 1782 } else {
1789 ASSERT(info == DONT_KNOW); 1783 ASSERT(info == DONT_KNOW);
1790 // We have to compile the test expression if we don't know its value 1784 // We have to compile the test expression if it can be reached by
1791 // and it can be reached by control flow falling out of the body or 1785 // control flow falling out of the body or via continue.
1792 // via continue.
1793 if (frame_ != NULL || node->continue_target()->is_linked()) { 1786 if (frame_ != NULL || node->continue_target()->is_linked()) {
1794 node->continue_target()->Bind(); 1787 node->continue_target()->Bind();
1795 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, 1788 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
1796 &body, node->break_target(), true); 1789 &body, node->break_target(), true);
1797 if (frame_ != NULL) { 1790 if (frame_ != NULL) {
1798 // A NULL frame here indicates that control flow did not fall 1791 // A NULL frame here indicates that control flow did not fall
1799 // out of the test expression. 1792 // out of the test expression.
1800 Branch(true, &body); 1793 Branch(true, &body);
1801 } 1794 }
1802 } 1795 }
1803 } 1796 }
1804 break; 1797 break;
1805 } 1798 }
1806 1799
1807 case LoopStatement::WHILE_LOOP: { 1800 case LoopStatement::WHILE_LOOP: {
1808
1809 JumpTarget body(this); 1801 JumpTarget body(this);
1810
1811 IncrementLoopNesting(); 1802 IncrementLoopNesting();
1812 // Generate the loop header. 1803 // Generate the loop header.
1813 if (info == ALWAYS_TRUE) { 1804 if (info == ALWAYS_TRUE) {
1814 // Merely label the body with the continue target. 1805 // Merely label the body with the continue target.
1815 node->continue_target()->Bind(); 1806 node->continue_target()->Bind();
1816 } else if (info == ALWAYS_FALSE) { 1807 } else if (info == ALWAYS_FALSE) {
1817 // There is no need to even compile the test or body. 1808 // There is no need to even compile the test or body.
1818 break; 1809 break;
1819 } else { 1810 } else {
1820 // Compile the test labeled with the continue target and label the 1811 // Compile the test labeled with the continue target and label the
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1919 1910
1920 // We keep stuff on the stack while the body is executing. 1911 // We keep stuff on the stack while the body is executing.
1921 // Record it, so that a break/continue crossing this statement 1912 // Record it, so that a break/continue crossing this statement
1922 // can restore the stack. 1913 // can restore the stack.
1923 const int kForInStackSize = 5 * kPointerSize; 1914 const int kForInStackSize = 5 * kPointerSize;
1924 break_stack_height_ += kForInStackSize; 1915 break_stack_height_ += kForInStackSize;
1925 node->set_break_stack_height(break_stack_height_); 1916 node->set_break_stack_height(break_stack_height_);
1926 node->break_target()->set_code_generator(this); 1917 node->break_target()->set_code_generator(this);
1927 node->continue_target()->set_code_generator(this); 1918 node->continue_target()->set_code_generator(this);
1928 1919
1920 JumpTarget primitive(this);
1921 JumpTarget jsobject(this);
1922 JumpTarget fixed_array(this);
1929 JumpTarget entry(this); 1923 JumpTarget entry(this);
1924 JumpTarget end_del_check(this);
1930 JumpTarget cleanup(this); 1925 JumpTarget cleanup(this);
1931 JumpTarget exit(this); 1926 JumpTarget exit(this);
1932 JumpTarget primitive(this);
1933 JumpTarget jsobject(this);
1934 JumpTarget end_del_check(this);
1935 JumpTarget fixed_array(this);
1936 1927
1937 // Get the object to enumerate over (converted to JSObject). 1928 // Get the object to enumerate over (converted to JSObject).
1938 Load(node->enumerable()); 1929 Load(node->enumerable());
1939 1930
1940 // Both SpiderMonkey and kjs ignore null and undefined in contrast 1931 // Both SpiderMonkey and kjs ignore null and undefined in contrast
1941 // to the specification. 12.6.4 mandates a call to ToObject. 1932 // to the specification. 12.6.4 mandates a call to ToObject.
1942 frame_->Pop(eax); 1933 frame_->Pop(eax);
1943 1934
1944 // eax: value to be iterated over 1935 // eax: value to be iterated over
1945 __ cmp(eax, Factory::undefined_value()); 1936 __ cmp(eax, Factory::undefined_value());
(...skipping 15 matching lines...) Expand all
1961 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 1952 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
1962 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 1953 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
1963 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 1954 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
1964 jsobject.Branch(above_equal); 1955 jsobject.Branch(above_equal);
1965 1956
1966 primitive.Bind(); 1957 primitive.Bind();
1967 frame_->Push(eax); 1958 frame_->Push(eax);
1968 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1); 1959 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1);
1969 // function call returns the value in eax, which is where we want it below 1960 // function call returns the value in eax, which is where we want it below
1970 1961
1971
1972 jsobject.Bind(); 1962 jsobject.Bind();
1973
1974 // Get the set of properties (as a FixedArray or Map). 1963 // Get the set of properties (as a FixedArray or Map).
1975 // eax: value to be iterated over 1964 // eax: value to be iterated over
1976 frame_->Push(eax); // push the object being iterated over (slot 4) 1965 frame_->Push(eax); // push the object being iterated over (slot 4)
1977 1966
1978 frame_->Push(eax); // push the Object (slot 4) for the runtime call 1967 frame_->Push(eax); // push the Object (slot 4) for the runtime call
1979 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1968 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1980 1969
1981 // If we got a Map, we can do a fast modification check. 1970 // If we got a Map, we can do a fast modification check.
1982 // Otherwise, we got a FixedArray, and we have to do a slow check. 1971 // Otherwise, we got a FixedArray, and we have to do a slow check.
1983 // eax: map or fixed array (result from call to 1972 // eax: map or fixed array (result from call to
(...skipping 13 matching lines...) Expand all
1997 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1986 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1998 1987
1999 frame_->Push(eax); // <- slot 3 1988 frame_->Push(eax); // <- slot 3
2000 frame_->Push(edx); // <- slot 2 1989 frame_->Push(edx); // <- slot 2
2001 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); 1990 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
2002 __ shl(eax, kSmiTagSize); 1991 __ shl(eax, kSmiTagSize);
2003 frame_->Push(eax); // <- slot 1 1992 frame_->Push(eax); // <- slot 1
2004 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0 1993 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0
2005 entry.Jump(); 1994 entry.Jump();
2006 1995
2007
2008 fixed_array.Bind(); 1996 fixed_array.Bind();
2009
2010 // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast) 1997 // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast)
2011 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 3 1998 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 3
2012 frame_->Push(eax); // <- slot 2 1999 frame_->Push(eax); // <- slot 2
2013 2000
2014 // Push the length of the array and the initial index onto the stack. 2001 // Push the length of the array and the initial index onto the stack.
2015 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); 2002 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
2016 __ shl(eax, kSmiTagSize); 2003 __ shl(eax, kSmiTagSize);
2017 frame_->Push(eax); // <- slot 1 2004 frame_->Push(eax); // <- slot 1
2018 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0 2005 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0
2019 2006
2020 // Condition. 2007 // Condition.
2021 entry.Bind(); 2008 entry.Bind();
2022
2023 __ mov(eax, frame_->ElementAt(0)); // load the current count 2009 __ mov(eax, frame_->ElementAt(0)); // load the current count
2024 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length 2010 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length
2025 cleanup.Branch(above_equal); 2011 cleanup.Branch(above_equal);
2026 2012
2027 // Get the i'th entry of the array. 2013 // Get the i'th entry of the array.
2028 __ mov(edx, frame_->ElementAt(2)); 2014 __ mov(edx, frame_->ElementAt(2));
2029 __ mov(ebx, Operand(edx, eax, times_2, 2015 __ mov(ebx, Operand(edx, eax, times_2,
2030 FixedArray::kHeaderSize - kHeapObjectTag)); 2016 FixedArray::kHeaderSize - kHeapObjectTag));
2031 2017
2032 // Get the expected map from the stack or a zero map in the 2018 // Get the expected map from the stack or a zero map in the
(...skipping 14 matching lines...) Expand all
2047 frame_->Push(frame_->ElementAt(4)); // push enumerable 2033 frame_->Push(frame_->ElementAt(4)); // push enumerable
2048 frame_->Push(ebx); // push entry 2034 frame_->Push(ebx); // push entry
2049 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2); 2035 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2);
2050 __ mov(ebx, Operand(eax)); 2036 __ mov(ebx, Operand(eax));
2051 2037
2052 // If the property has been removed while iterating, we just skip it. 2038 // If the property has been removed while iterating, we just skip it.
2053 __ cmp(ebx, Factory::null_value()); 2039 __ cmp(ebx, Factory::null_value());
2054 node->continue_target()->Branch(equal); 2040 node->continue_target()->Branch(equal);
2055 2041
2056 end_del_check.Bind(); 2042 end_del_check.Bind();
2057 // Store the entry in the 'each' expression and take another spin in the loop. 2043 // Store the entry in the 'each' expression and take another spin in the
2058 // edx: i'th entry of the enum cache (or string there of) 2044 // loop. edx: i'th entry of the enum cache (or string there of)
2059 frame_->Push(ebx); 2045 frame_->Push(ebx);
2060 { Reference each(this, node->each()); 2046 { Reference each(this, node->each());
2061 if (!each.is_illegal()) { 2047 if (!each.is_illegal()) {
2062 if (each.size() > 0) { 2048 if (each.size() > 0) {
2063 frame_->Push(frame_->ElementAt(each.size())); 2049 frame_->Push(frame_->ElementAt(each.size()));
2064 } 2050 }
2065 // If the reference was to a slot we rely on the convenient property 2051 // If the reference was to a slot we rely on the convenient property
2066 // that it doesn't matter whether a value (eg, ebx pushed above) is 2052 // that it doesn't matter whether a value (eg, ebx pushed above) is
2067 // right on top of or right underneath a zero-sized reference. 2053 // right on top of or right underneath a zero-sized reference.
2068 each.SetValue(NOT_CONST_INIT); 2054 each.SetValue(NOT_CONST_INIT);
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
2203 // break from (eg, for...in) may have left stuff on the stack. 2189 // break from (eg, for...in) may have left stuff on the stack.
2204 __ mov(edx, Operand::StaticVariable(handler_address)); 2190 __ mov(edx, Operand::StaticVariable(handler_address));
2205 const int kNextOffset = StackHandlerConstants::kNextOffset + 2191 const int kNextOffset = StackHandlerConstants::kNextOffset +
2206 StackHandlerConstants::kAddressDisplacement; 2192 StackHandlerConstants::kAddressDisplacement;
2207 __ lea(esp, Operand(edx, kNextOffset)); 2193 __ lea(esp, Operand(edx, kNextOffset));
2208 frame_->Forget(frame_->height() - handler_height); 2194 frame_->Forget(frame_->height() - handler_height);
2209 2195
2210 frame_->Pop(Operand::StaticVariable(handler_address)); 2196 frame_->Pop(Operand::StaticVariable(handler_address));
2211 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2197 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2212 // next_sp popped. 2198 // next_sp popped.
2213 JumpTarget* original_target = shadows[i]->original_target(); 2199 shadows[i]->original_target()->Jump();
2214 original_target->Jump();
2215 } 2200 }
2216 } 2201 }
2217 2202
2218 exit.Bind(); 2203 exit.Bind();
2219 } 2204 }
2220 2205
2221 2206
2222 void CodeGenerator::VisitTryFinally(TryFinally* node) { 2207 void CodeGenerator::VisitTryFinally(TryFinally* node) {
2223 Comment cmnt(masm_, "[ TryFinally"); 2208 Comment cmnt(masm_, "[ TryFinally");
2224 2209
2225 // State: Used to keep track of reason for entering the finally 2210 // State: Used to keep track of reason for entering the finally
2226 // block. Should probably be extended to hold information for 2211 // block. Should probably be extended to hold information for
2227 // break/continue from within the try block. 2212 // break/continue from within the try block.
2228 enum { FALLING, THROWING, JUMPING }; 2213 enum { FALLING, THROWING, JUMPING };
2229 2214
2230 JumpTarget exit(this);
2231 JumpTarget unlink(this); 2215 JumpTarget unlink(this);
2232 JumpTarget try_block(this); 2216 JumpTarget try_block(this);
2233 JumpTarget finally_block(this); 2217 JumpTarget finally_block(this);
2234 2218
2235 try_block.Call(); 2219 try_block.Call();
2236 2220
2237 frame_->Push(eax); 2221 frame_->Push(eax);
2238 // In case of thrown exceptions, this is where we continue. 2222 // In case of thrown exceptions, this is where we continue.
2239 __ Set(ecx, Immediate(Smi::FromInt(THROWING))); 2223 __ Set(ecx, Immediate(Smi::FromInt(THROWING)));
2240 finally_block.Jump(); 2224 finally_block.Jump();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2335 // that a break/continue crossing this statement can restore the 2319 // that a break/continue crossing this statement can restore the
2336 // stack. 2320 // stack.
2337 const int kFinallyStackSize = 2 * kPointerSize; 2321 const int kFinallyStackSize = 2 * kPointerSize;
2338 break_stack_height_ += kFinallyStackSize; 2322 break_stack_height_ += kFinallyStackSize;
2339 2323
2340 // Generate code for the statements in the finally block. 2324 // Generate code for the statements in the finally block.
2341 VisitStatements(node->finally_block()->statements()); 2325 VisitStatements(node->finally_block()->statements());
2342 2326
2343 break_stack_height_ -= kFinallyStackSize; 2327 break_stack_height_ -= kFinallyStackSize;
2344 if (frame_ != NULL) { 2328 if (frame_ != NULL) {
2329 JumpTarget exit(this);
2345 // Restore state and return value or faked TOS. 2330 // Restore state and return value or faked TOS.
2346 frame_->Pop(ecx); 2331 frame_->Pop(ecx);
2347 frame_->Pop(eax); 2332 frame_->Pop(eax);
2348 2333
2349 // Generate code to jump to the right destination for all used 2334 // Generate code to jump to the right destination for all used
2350 // (formerly) shadowing targets. 2335 // (formerly) shadowing targets.
2351 for (int i = 0; i <= nof_escapes; i++) { 2336 for (int i = 0; i <= nof_escapes; i++) {
2352 if (shadows[i]->is_bound()) { 2337 if (shadows[i]->is_bound()) {
2353 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); 2338 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i)));
2354 shadows[i]->original_target()->Branch(equal); 2339 shadows[i]->original_target()->Branch(equal);
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
2637 case ObjectLiteral::Property::CONSTANT: break; 2622 case ObjectLiteral::Property::CONSTANT: break;
2638 case ObjectLiteral::Property::COMPUTED: { 2623 case ObjectLiteral::Property::COMPUTED: {
2639 Handle<Object> key(property->key()->handle()); 2624 Handle<Object> key(property->key()->handle());
2640 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2625 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
2641 if (key->IsSymbol()) { 2626 if (key->IsSymbol()) {
2642 __ mov(eax, frame_->Top()); 2627 __ mov(eax, frame_->Top());
2643 frame_->Push(eax); 2628 frame_->Push(eax);
2644 Load(property->value()); 2629 Load(property->value());
2645 frame_->Pop(eax); 2630 frame_->Pop(eax);
2646 __ Set(ecx, Immediate(key)); 2631 __ Set(ecx, Immediate(key));
2647 frame_->CallCode(ic, RelocInfo::CODE_TARGET, 0); 2632 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
2648 frame_->Drop(); 2633 frame_->Drop();
2649 // Ignore result. 2634 // Ignore result.
2650 break; 2635 break;
2651 } 2636 }
2652 // Fall through 2637 // Fall through
2653 } 2638 }
2654 case ObjectLiteral::Property::PROTOTYPE: { 2639 case ObjectLiteral::Property::PROTOTYPE: {
2655 __ mov(eax, frame_->Top()); 2640 __ mov(eax, frame_->Top());
2656 frame_->Push(eax); 2641 frame_->Push(eax);
2657 Load(property->key()); 2642 Load(property->key());
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2835 2820
2836 // Push the name of the function and the receiver onto the stack. 2821 // Push the name of the function and the receiver onto the stack.
2837 frame_->Push(Immediate(var->name())); 2822 frame_->Push(Immediate(var->name()));
2838 2823
2839 // Pass the global object as the receiver and let the IC stub 2824 // Pass the global object as the receiver and let the IC stub
2840 // patch the stack to use the global proxy as 'this' in the 2825 // patch the stack to use the global proxy as 'this' in the
2841 // invoked function. 2826 // invoked function.
2842 LoadGlobal(); 2827 LoadGlobal();
2843 2828
2844 // Load the arguments. 2829 // Load the arguments.
2845 for (int i = 0; i < args->length(); i++) { 2830 int arg_count = args->length();
2831 for (int i = 0; i < arg_count; i++) {
2846 Load(args->at(i)); 2832 Load(args->at(i));
2847 } 2833 }
2848 2834
2849 // Setup the receiver register and call the IC initialization code. 2835 // Setup the receiver register and call the IC initialization code.
2850 Handle<Code> stub = ComputeCallInitialize(args->length()); 2836 Handle<Code> stub = ComputeCallInitialize(arg_count);
2851 __ RecordPosition(node->position()); 2837 __ RecordPosition(node->position());
2852 frame_->CallCode(stub, RelocInfo::CODE_TARGET_CONTEXT, args->length() + 1); 2838 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
2839 arg_count + 1);
2853 __ mov(esi, frame_->Context()); 2840 __ mov(esi, frame_->Context());
2854 2841
2855 // Overwrite the function on the stack with the result. 2842 // Overwrite the function on the stack with the result.
2856 __ mov(frame_->Top(), eax); 2843 __ mov(frame_->Top(), eax);
2857 2844
2858 } else if (var != NULL && var->slot() != NULL && 2845 } else if (var != NULL && var->slot() != NULL &&
2859 var->slot()->type() == Slot::LOOKUP) { 2846 var->slot()->type() == Slot::LOOKUP) {
2860 // ---------------------------------- 2847 // ----------------------------------
2861 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj 2848 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj
2862 // ---------------------------------- 2849 // ----------------------------------
(...skipping 18 matching lines...) Expand all
2881 if (literal != NULL && literal->handle()->IsSymbol()) { 2868 if (literal != NULL && literal->handle()->IsSymbol()) {
2882 // ------------------------------------------------------------------ 2869 // ------------------------------------------------------------------
2883 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 2870 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
2884 // ------------------------------------------------------------------ 2871 // ------------------------------------------------------------------
2885 2872
2886 // Push the name of the function and the receiver onto the stack. 2873 // Push the name of the function and the receiver onto the stack.
2887 frame_->Push(Immediate(literal->handle())); 2874 frame_->Push(Immediate(literal->handle()));
2888 Load(property->obj()); 2875 Load(property->obj());
2889 2876
2890 // Load the arguments. 2877 // Load the arguments.
2891 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 2878 int arg_count = args->length();
2879 for (int i = 0; i < arg_count; i++) {
2880 Load(args->at(i));
2881 }
2892 2882
2893 // Call the IC initialization code. 2883 // Call the IC initialization code.
2894 Handle<Code> stub = ComputeCallInitialize(args->length()); 2884 Handle<Code> stub = ComputeCallInitialize(arg_count);
2895 __ RecordPosition(node->position()); 2885 __ RecordPosition(node->position());
2896 frame_->CallCode(stub, RelocInfo::CODE_TARGET, args->length() + 1); 2886 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
2897 __ mov(esi, frame_->Context()); 2887 __ mov(esi, frame_->Context());
2898 2888
2899 // Overwrite the function on the stack with the result. 2889 // Overwrite the function on the stack with the result.
2900 __ mov(frame_->Top(), eax); 2890 __ mov(frame_->Top(), eax);
2901 2891
2902 } else { 2892 } else {
2903 // ------------------------------------------- 2893 // -------------------------------------------
2904 // JavaScript example: 'array[index](1, 2, 3)' 2894 // JavaScript example: 'array[index](1, 2, 3)'
2905 // ------------------------------------------- 2895 // -------------------------------------------
2906 2896
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2943 // evaluated. 2933 // evaluated.
2944 2934
2945 // Compute function to call and use the global object as the 2935 // Compute function to call and use the global object as the
2946 // receiver. There is no need to use the global proxy here because 2936 // receiver. There is no need to use the global proxy here because
2947 // it will always be replaced with a newly allocated object. 2937 // it will always be replaced with a newly allocated object.
2948 Load(node->expression()); 2938 Load(node->expression());
2949 LoadGlobal(); 2939 LoadGlobal();
2950 2940
2951 // Push the arguments ("left-to-right") on the stack. 2941 // Push the arguments ("left-to-right") on the stack.
2952 ZoneList<Expression*>* args = node->arguments(); 2942 ZoneList<Expression*>* args = node->arguments();
2953 for (int i = 0; i < args->length(); i++) { 2943 int arg_count = args->length();
2944 for (int i = 0; i < arg_count; i++) {
2954 Load(args->at(i)); 2945 Load(args->at(i));
2955 } 2946 }
2956 2947
2957 // Constructors are called with the number of arguments in register 2948 // Constructors are called with the number of arguments in register
2958 // eax for now. Another option would be to have separate construct 2949 // eax for now. Another option would be to have separate construct
2959 // call trampolines per different arguments counts encountered. 2950 // call trampolines per different arguments counts encountered.
2960 __ Set(eax, Immediate(args->length())); 2951 __ Set(eax, Immediate(arg_count));
2961 2952
2962 // Load the function into temporary function slot as per calling 2953 // Load the function into temporary function slot as per calling
2963 // convention. 2954 // convention.
2964 __ mov(edi, frame_->ElementAt(args->length() + 1)); 2955 __ mov(edi, frame_->ElementAt(arg_count + 1));
2965 2956
2966 // Call the construct call builtin that handles allocation and 2957 // Call the construct call builtin that handles allocation and
2967 // constructor invocation. 2958 // constructor invocation.
2968 __ RecordPosition(node->position()); 2959 __ RecordPosition(node->position());
2969 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); 2960 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
2970 frame_->CallCode(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1); 2961 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1);
2971 // Discard the function and "push" the newly created object. 2962 // Discard the function and "push" the newly created object.
2972 __ mov(frame_->Top(), eax); 2963 __ mov(frame_->Top(), eax);
2973 } 2964 }
2974 2965
2975 2966
2976 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 2967 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
2977 ASSERT(args->length() == 1); 2968 ASSERT(args->length() == 1);
2978 Load(args->at(0)); 2969 Load(args->at(0));
2979 frame_->Pop(eax); 2970 frame_->Pop(eax);
2980 __ test(eax, Immediate(kSmiTagMask)); 2971 __ test(eax, Immediate(kSmiTagMask));
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
3235 3226
3236 if (function == NULL) { 3227 if (function == NULL) {
3237 // Prepare stack for calling JS runtime function. 3228 // Prepare stack for calling JS runtime function.
3238 frame_->Push(Immediate(node->name())); 3229 frame_->Push(Immediate(node->name()));
3239 // Push the builtins object found in the current global object. 3230 // Push the builtins object found in the current global object.
3240 __ mov(edx, GlobalObject()); 3231 __ mov(edx, GlobalObject());
3241 frame_->Push(FieldOperand(edx, GlobalObject::kBuiltinsOffset)); 3232 frame_->Push(FieldOperand(edx, GlobalObject::kBuiltinsOffset));
3242 } 3233 }
3243 3234
3244 // Push the arguments ("left-to-right"). 3235 // Push the arguments ("left-to-right").
3245 for (int i = 0; i < args->length(); i++) { 3236 int arg_count = args->length();
3237 for (int i = 0; i < arg_count; i++) {
3246 Load(args->at(i)); 3238 Load(args->at(i));
3247 } 3239 }
3248 3240
3249 if (function == NULL) { 3241 if (function == NULL) {
3250 // Call the JS runtime function. 3242 // Call the JS runtime function.
3251 Handle<Code> stub = ComputeCallInitialize(args->length()); 3243 Handle<Code> stub = ComputeCallInitialize(arg_count);
3252 __ Set(eax, Immediate(args->length())); 3244 __ Set(eax, Immediate(args->length()));
3253 frame_->CallCode(stub, RelocInfo::CODE_TARGET, args->length() + 1); 3245 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
3254 __ mov(esi, frame_->Context()); 3246 __ mov(esi, frame_->Context());
3255 __ mov(frame_->Top(), eax); 3247 __ mov(frame_->Top(), eax);
3256 } else { 3248 } else {
3257 // Call the C runtime function. 3249 // Call the C runtime function.
3258 frame_->CallRuntime(function, args->length()); 3250 frame_->CallRuntime(function, arg_count);
3259 frame_->Push(eax); 3251 frame_->Push(eax);
3260 } 3252 }
3261 } 3253 }
3262 3254
3263 3255
3264 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 3256 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
3265 // Note that because of NOT and an optimization in comparison of a typeof 3257 // Note that because of NOT and an optimization in comparison of a typeof
3266 // expression to a literal string, this function can fail to leave a value 3258 // expression to a literal string, this function can fail to leave a value
3267 // on top of the frame or in the cc register. 3259 // on top of the frame or in the cc register.
3268 Comment cmnt(masm_, "[ UnaryOperation"); 3260 Comment cmnt(masm_, "[ UnaryOperation");
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after
3961 // loads must not throw a reference error). 3953 // loads must not throw a reference error).
3962 Comment cmnt(masm, "[ Load from named Property"); 3954 Comment cmnt(masm, "[ Load from named Property");
3963 Handle<String> name(GetName()); 3955 Handle<String> name(GetName());
3964 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3956 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3965 // Setup the name register. 3957 // Setup the name register.
3966 __ mov(ecx, name); 3958 __ mov(ecx, name);
3967 3959
3968 Variable* var = expression_->AsVariableProxy()->AsVariable(); 3960 Variable* var = expression_->AsVariableProxy()->AsVariable();
3969 if (var != NULL) { 3961 if (var != NULL) {
3970 ASSERT(var->is_global()); 3962 ASSERT(var->is_global());
3971 frame->CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 3963 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
3972 } else { 3964 } else {
3973 frame->CallCode(ic, RelocInfo::CODE_TARGET, 0); 3965 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
3974 } 3966 }
3975 frame->Push(eax); // IC call leaves result in eax, push it out 3967 frame->Push(eax); // IC call leaves result in eax, push it out
3976 break; 3968 break;
3977 } 3969 }
3978 3970
3979 case KEYED: { 3971 case KEYED: {
3980 // TODO(1241834): Make sure that this it is safe to ignore the 3972 // TODO(1241834): Make sure that this it is safe to ignore the
3981 // distinction between expressions in a typeof and not in a typeof. 3973 // distinction between expressions in a typeof and not in a typeof.
3982 Comment cmnt(masm, "[ Load from keyed Property"); 3974 Comment cmnt(masm, "[ Load from keyed Property");
3983 Property* property = expression_->AsProperty(); 3975 Property* property = expression_->AsProperty();
3984 ASSERT(property != NULL); 3976 ASSERT(property != NULL);
3985 __ RecordPosition(property->position()); 3977 __ RecordPosition(property->position());
3986 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 3978 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
3987 3979
3988 Variable* var = expression_->AsVariableProxy()->AsVariable(); 3980 Variable* var = expression_->AsVariableProxy()->AsVariable();
3989 if (var != NULL) { 3981 if (var != NULL) {
3990 ASSERT(var->is_global()); 3982 ASSERT(var->is_global());
3991 frame->CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 3983 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
3992 } else { 3984 } else {
3993 frame->CallCode(ic, RelocInfo::CODE_TARGET, 0); 3985 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
3994 } 3986 }
3995 frame->Push(eax); // IC call leaves result in eax, push it out 3987 frame->Push(eax); // IC call leaves result in eax, push it out
3996 break; 3988 break;
3997 } 3989 }
3998 3990
3999 default: 3991 default:
4000 UNREACHABLE(); 3992 UNREACHABLE();
4001 } 3993 }
4002 } 3994 }
4003 3995
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
4087 4079
4088 case NAMED: { 4080 case NAMED: {
4089 Comment cmnt(masm, "[ Store to named Property"); 4081 Comment cmnt(masm, "[ Store to named Property");
4090 // Call the appropriate IC code. 4082 // Call the appropriate IC code.
4091 Handle<String> name(GetName()); 4083 Handle<String> name(GetName());
4092 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 4084 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
4093 // TODO(1222589): Make the IC grab the values from the stack. 4085 // TODO(1222589): Make the IC grab the values from the stack.
4094 frame->Pop(eax); 4086 frame->Pop(eax);
4095 // Setup the name register. 4087 // Setup the name register.
4096 __ mov(ecx, name); 4088 __ mov(ecx, name);
4097 frame->CallCode(ic, RelocInfo::CODE_TARGET, 0); 4089 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4098 frame->Push(eax); // IC call leaves result in eax, push it out 4090 frame->Push(eax); // IC call leaves result in eax, push it out
4099 break; 4091 break;
4100 } 4092 }
4101 4093
4102 case KEYED: { 4094 case KEYED: {
4103 Comment cmnt(masm, "[ Store to keyed Property"); 4095 Comment cmnt(masm, "[ Store to keyed Property");
4104 Property* property = expression_->AsProperty(); 4096 Property* property = expression_->AsProperty();
4105 ASSERT(property != NULL); 4097 ASSERT(property != NULL);
4106 __ RecordPosition(property->position()); 4098 __ RecordPosition(property->position());
4107 // Call IC code. 4099 // Call IC code.
4108 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 4100 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
4109 // TODO(1222589): Make the IC grab the values from the stack. 4101 // TODO(1222589): Make the IC grab the values from the stack.
4110 frame->Pop(eax); 4102 frame->Pop(eax);
4111 frame->CallCode(ic, RelocInfo::CODE_TARGET, 0); 4103 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4112 frame->Push(eax); // IC call leaves result in eax, push it out 4104 frame->Push(eax); // IC call leaves result in eax, push it out
4113 break; 4105 break;
4114 } 4106 }
4115 4107
4116 default: 4108 default:
4117 UNREACHABLE(); 4109 UNREACHABLE();
4118 } 4110 }
4119 } 4111 }
4120 4112
4121 4113
(...skipping 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after
5337 5329
5338 // Slow-case: Go through the JavaScript implementation. 5330 // Slow-case: Go through the JavaScript implementation.
5339 __ bind(&slow); 5331 __ bind(&slow);
5340 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5332 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5341 } 5333 }
5342 5334
5343 5335
5344 #undef __ 5336 #undef __
5345 5337
5346 } } // namespace v8::internal 5338 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-arm.cc ('k') | src/jump-target-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698