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

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

Issue 9769: Add state to track the individual elements of the virtual frame.... (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 | « no previous file | src/jump-target-ia32.cc » ('j') | src/virtual-frame-ia32.h » ('J')
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 14 matching lines...) Expand all
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "bootstrapper.h" 30 #include "bootstrapper.h"
31 #include "codegen-inl.h" 31 #include "codegen-inl.h"
32 #include "debug.h" 32 #include "debug.h"
33 #include "scopes.h" 33 #include "scopes.h"
34 #include "runtime.h" 34 #include "runtime.h"
35 #include "virtual-frame-ia32-inl.h"
36 35
37 namespace v8 { namespace internal { 36 namespace v8 { namespace internal {
38 37
39 #define __ masm_-> 38 #define __ masm_->
40 39
41 // ------------------------------------------------------------------------- 40 // -------------------------------------------------------------------------
42 // CodeGenState implementation. 41 // CodeGenState implementation.
43 42
44 CodeGenState::CodeGenState(CodeGenerator* owner) 43 CodeGenState::CodeGenState(CodeGenerator* owner)
45 : owner_(owner), 44 : owner_(owner),
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 __ lea(eax, frame_->Receiver()); 148 __ lea(eax, frame_->Receiver());
150 frame_->Push(frame_->Function()); 149 frame_->Push(frame_->Function());
151 frame_->Push(eax); 150 frame_->Push(eax);
152 frame_->Push(Immediate(Smi::FromInt(scope_->num_parameters()))); 151 frame_->Push(Immediate(Smi::FromInt(scope_->num_parameters())));
153 frame_->CallStub(&stub, 3); 152 frame_->CallStub(&stub, 3);
154 __ mov(ecx, Operand(eax)); 153 __ mov(ecx, Operand(eax));
155 arguments_object_allocated = true; 154 arguments_object_allocated = true;
156 } 155 }
157 156
158 // Allocate space for locals and initialize them. 157 // Allocate space for locals and initialize them.
159 frame_->AllocateLocals(); 158 frame_->AllocateLocals(scope_->num_stack_slots());
Erik Corry 2008/11/11 10:47:05 Should AllocateLocals be called AllocateStackSlots
Kevin Millikin (Chromium) 2008/11/11 11:37:31 Probably. Changed.
160 159
161 if (scope_->num_heap_slots() > 0) { 160 if (scope_->num_heap_slots() > 0) {
162 Comment cmnt(masm_, "[ allocate local context"); 161 Comment cmnt(masm_, "[ allocate local context");
163 // Save the arguments object pointer, if any. 162 // Save the arguments object pointer, if any.
164 if (arguments_object_allocated && !arguments_object_saved) { 163 if (arguments_object_allocated && !arguments_object_saved) {
165 frame_->Push(ecx); 164 frame_->Push(ecx);
166 arguments_object_saved = true; 165 arguments_object_saved = true;
167 } 166 }
168 // Allocate local context. 167 // Allocate local context.
169 // Get outer context and create a new context based on it. 168 // Get outer context and create a new context based on it.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 // If the newly-allocated argument object is not already on 239 // If the newly-allocated argument object is not already on
241 // the stack, we rely on the property that loading a 240 // the stack, we rely on the property that loading a
242 // zero-sized reference will not clobber the ecx register. 241 // zero-sized reference will not clobber the ecx register.
243 if (!arguments_object_saved) { 242 if (!arguments_object_saved) {
244 frame_->Push(ecx); 243 frame_->Push(ecx);
245 } 244 }
246 arguments_ref.SetValue(NOT_CONST_INIT); 245 arguments_ref.SetValue(NOT_CONST_INIT);
247 } 246 }
248 shadow_ref.SetValue(NOT_CONST_INIT); 247 shadow_ref.SetValue(NOT_CONST_INIT);
249 } 248 }
250 frame_->Pop(); // Value is no longer needed. 249 frame_->Drop(); // Value is no longer needed.
251 } 250 }
252 251
253 // Generate code to 'execute' declarations and initialize functions 252 // Generate code to 'execute' declarations and initialize functions
254 // (source elements). In case of an illegal redeclaration we need to 253 // (source elements). In case of an illegal redeclaration we need to
255 // handle that instead of processing the declarations. 254 // handle that instead of processing the declarations.
256 if (scope_->HasIllegalRedeclaration()) { 255 if (scope_->HasIllegalRedeclaration()) {
257 Comment cmnt(masm_, "[ illegal redeclarations"); 256 Comment cmnt(masm_, "[ illegal redeclarations");
258 scope_->VisitIllegalRedeclaration(this); 257 scope_->VisitIllegalRedeclaration(this);
259 } else { 258 } else {
260 Comment cmnt(masm_, "[ declarations"); 259 Comment cmnt(masm_, "[ declarations");
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 712
714 void CodeGenerator::GenericBinaryOperation(Token::Value op, 713 void CodeGenerator::GenericBinaryOperation(Token::Value op,
715 StaticType* type, 714 StaticType* type,
716 OverwriteMode overwrite_mode) { 715 OverwriteMode overwrite_mode) {
717 Comment cmnt(masm_, "[ BinaryOperation"); 716 Comment cmnt(masm_, "[ BinaryOperation");
718 Comment cmnt_token(masm_, Token::String(op)); 717 Comment cmnt_token(masm_, Token::String(op));
719 718
720 if (op == Token::COMMA) { 719 if (op == Token::COMMA) {
721 // Simply discard left value. 720 // Simply discard left value.
722 frame_->Pop(eax); 721 frame_->Pop(eax);
723 frame_->Pop(); 722 frame_->Drop();
724 frame_->Push(eax); 723 frame_->Push(eax);
725 return; 724 return;
726 } 725 }
727 726
728 // Set the flags based on the operation, type and loop nesting level. 727 // Set the flags based on the operation, type and loop nesting level.
729 GenericBinaryFlags flags; 728 GenericBinaryFlags flags;
730 switch (op) { 729 switch (op) {
731 case Token::BIT_OR: 730 case Token::BIT_OR:
732 case Token::BIT_AND: 731 case Token::BIT_AND:
733 case Token::BIT_XOR: 732 case Token::BIT_XOR:
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after
1357 if (val != NULL) { 1356 if (val != NULL) {
1358 // Set initial value. 1357 // Set initial value.
1359 Reference target(this, node->proxy()); 1358 Reference target(this, node->proxy());
1360 ASSERT(target.is_slot()); 1359 ASSERT(target.is_slot());
1361 Load(val); 1360 Load(val);
1362 target.SetValue(NOT_CONST_INIT); 1361 target.SetValue(NOT_CONST_INIT);
1363 // Get rid of the assigned value (declarations are statements). It's 1362 // Get rid of the assigned value (declarations are statements). It's
1364 // safe to pop the value lying on top of the reference before unloading 1363 // safe to pop the value lying on top of the reference before unloading
1365 // the reference itself (which preserves the top of stack) because we 1364 // the reference itself (which preserves the top of stack) because we
1366 // know that it is a zero-sized reference. 1365 // know that it is a zero-sized reference.
1367 frame_->Pop(); 1366 frame_->Drop();
1368 } 1367 }
1369 } 1368 }
1370 1369
1371 1370
1372 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { 1371 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
1373 Comment cmnt(masm_, "[ ExpressionStatement"); 1372 Comment cmnt(masm_, "[ ExpressionStatement");
1374 RecordStatementPosition(node); 1373 RecordStatementPosition(node);
1375 Expression* expression = node->expression(); 1374 Expression* expression = node->expression();
1376 expression->MarkAsStatement(); 1375 expression->MarkAsStatement();
1377 Load(expression); 1376 Load(expression);
1378 // Remove the lingering expression result from the top of stack. 1377 // Remove the lingering expression result from the top of stack.
1379 frame_->Pop(); 1378 frame_->Drop();
1380 } 1379 }
1381 1380
1382 1381
1383 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { 1382 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
1384 Comment cmnt(masm_, "// EmptyStatement"); 1383 Comment cmnt(masm_, "// EmptyStatement");
1385 // nothing to do 1384 // nothing to do
1386 } 1385 }
1387 1386
1388 1387
1389 void CodeGenerator::VisitIfStatement(IfStatement* node) { 1388 void CodeGenerator::VisitIfStatement(IfStatement* node) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1458 } else { 1457 } else {
1459 ASSERT(!has_then_stm && !has_else_stm); 1458 ASSERT(!has_then_stm && !has_else_stm);
1460 // if (cond) 1459 // if (cond)
1461 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false); 1460 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false);
1462 if (frame_ != NULL) { 1461 if (frame_ != NULL) {
1463 if (has_cc()) { 1462 if (has_cc()) {
1464 cc_reg_ = no_condition; 1463 cc_reg_ = no_condition;
1465 } else { 1464 } else {
1466 // No cc value set up, that means the boolean was pushed. 1465 // No cc value set up, that means the boolean was pushed.
1467 // Pop it again, since it is not going to be used. 1466 // Pop it again, since it is not going to be used.
1468 frame_->Pop(); 1467 frame_->Drop();
1469 } 1468 }
1470 } 1469 }
1471 } 1470 }
1472 1471
1473 // end 1472 // end
1474 if (exit.is_linked()) { 1473 if (exit.is_linked()) {
1475 exit.Bind(); 1474 exit.Bind();
1476 } 1475 }
1477 } 1476 }
1478 1477
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
1677 next_test.Bind(); 1676 next_test.Bind();
1678 next_test.Unuse(); 1677 next_test.Unuse();
1679 // Duplicate TOS. 1678 // Duplicate TOS.
1680 __ mov(eax, frame_->Top()); 1679 __ mov(eax, frame_->Top());
1681 frame_->Push(eax); 1680 frame_->Push(eax);
1682 Load(clause->label()); 1681 Load(clause->label());
1683 Comparison(equal, true); 1682 Comparison(equal, true);
1684 Branch(false, &next_test); 1683 Branch(false, &next_test);
1685 1684
1686 // Before entering the body, remove the switch value from the stack. 1685 // Before entering the body, remove the switch value from the stack.
1687 frame_->Pop(); 1686 frame_->Drop();
1688 1687
1689 // Label the body so that fall through is enabled. 1688 // Label the body so that fall through is enabled.
1690 if (i > 0 && cases->at(i - 1)->is_default()) { 1689 if (i > 0 && cases->at(i - 1)->is_default()) {
1691 default_exit.Bind(); 1690 default_exit.Bind();
1692 } else { 1691 } else {
1693 fall_through.Bind(); 1692 fall_through.Bind();
1694 fall_through.Unuse(); 1693 fall_through.Unuse();
1695 } 1694 }
1696 VisitStatements(clause->statements()); 1695 VisitStatements(clause->statements());
1697 1696
1698 // If control flow can fall through from the body jump to the 1697 // If control flow can fall through from the body jump to the
1699 // next body or end of the statement. 1698 // next body or end of the statement.
1700 if (frame_ != NULL) { 1699 if (frame_ != NULL) {
1701 if (i < length - 1 && cases->at(i + 1)->is_default()) { 1700 if (i < length - 1 && cases->at(i + 1)->is_default()) {
1702 default_entry.Jump(); 1701 default_entry.Jump();
1703 } else { 1702 } else {
1704 fall_through.Jump(); 1703 fall_through.Jump();
1705 } 1704 }
1706 } 1705 }
1707 } 1706 }
1708 } 1707 }
1709 1708
1710 // The final test removes the switch value. 1709 // The final test removes the switch value.
1711 next_test.Bind(); 1710 next_test.Bind();
1712 frame_->Pop(); 1711 frame_->Drop();
1713 1712
1714 // If there is a default clause, compile it. 1713 // If there is a default clause, compile it.
1715 if (default_clause != NULL) { 1714 if (default_clause != NULL) {
1716 Comment cmnt(masm_, "[ Default clause"); 1715 Comment cmnt(masm_, "[ Default clause");
1717 default_entry.Bind(); 1716 default_entry.Bind();
1718 VisitStatements(default_clause->statements()); 1717 VisitStatements(default_clause->statements());
1719 // If control flow can fall out of the default and there is a case after 1718 // If control flow can fall out of the default and there is a case after
1720 // it, jump to that case's body. 1719 // it, jump to that case's body.
1721 if (frame_ != NULL && default_exit.is_bound()) { 1720 if (frame_ != NULL && default_exit.is_bound()) {
1722 default_exit.Jump(); 1721 default_exit.Jump();
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
2014 2013
2015 // Push the length of the array and the initial index onto the stack. 2014 // Push the length of the array and the initial index onto the stack.
2016 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); 2015 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
2017 __ shl(eax, kSmiTagSize); 2016 __ shl(eax, kSmiTagSize);
2018 frame_->Push(eax); // <- slot 1 2017 frame_->Push(eax); // <- slot 1
2019 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0 2018 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0
2020 2019
2021 // Condition. 2020 // Condition.
2022 entry.Bind(); 2021 entry.Bind();
2023 2022
2024 __ mov(eax, frame_->Element(0)); // load the current count 2023 __ mov(eax, frame_->ElementAt(0)); // load the current count
2025 __ cmp(eax, frame_->Element(1)); // compare to the array length 2024 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length
2026 cleanup.Branch(above_equal); 2025 cleanup.Branch(above_equal);
2027 2026
2028 // Get the i'th entry of the array. 2027 // Get the i'th entry of the array.
2029 __ mov(edx, frame_->Element(2)); 2028 __ mov(edx, frame_->ElementAt(2));
2030 __ mov(ebx, Operand(edx, eax, times_2, 2029 __ mov(ebx, Operand(edx, eax, times_2,
2031 FixedArray::kHeaderSize - kHeapObjectTag)); 2030 FixedArray::kHeaderSize - kHeapObjectTag));
2032 2031
2033 // Get the expected map from the stack or a zero map in the 2032 // Get the expected map from the stack or a zero map in the
2034 // permanent slow case eax: current iteration count ebx: i'th entry 2033 // permanent slow case eax: current iteration count ebx: i'th entry
2035 // of the enum cache 2034 // of the enum cache
2036 __ mov(edx, frame_->Element(3)); 2035 __ mov(edx, frame_->ElementAt(3));
2037 // Check if the expected map still matches that of the enumerable. 2036 // Check if the expected map still matches that of the enumerable.
2038 // If not, we have to filter the key. 2037 // If not, we have to filter the key.
2039 // eax: current iteration count 2038 // eax: current iteration count
2040 // ebx: i'th entry of the enum cache 2039 // ebx: i'th entry of the enum cache
2041 // edx: expected map value 2040 // edx: expected map value
2042 __ mov(ecx, frame_->Element(4)); 2041 __ mov(ecx, frame_->ElementAt(4));
2043 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); 2042 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
2044 __ cmp(ecx, Operand(edx)); 2043 __ cmp(ecx, Operand(edx));
2045 end_del_check.Branch(equal); 2044 end_del_check.Branch(equal);
2046 2045
2047 // Convert the entry to a string (or null if it isn't a property anymore). 2046 // Convert the entry to a string (or null if it isn't a property anymore).
2048 frame_->Push(frame_->Element(4)); // push enumerable 2047 frame_->Push(frame_->ElementAt(4)); // push enumerable
2049 frame_->Push(ebx); // push entry 2048 frame_->Push(ebx); // push entry
2050 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2); 2049 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2);
2051 __ mov(ebx, Operand(eax)); 2050 __ mov(ebx, Operand(eax));
2052 2051
2053 // If the property has been removed while iterating, we just skip it. 2052 // If the property has been removed while iterating, we just skip it.
2054 __ cmp(ebx, Factory::null_value()); 2053 __ cmp(ebx, Factory::null_value());
2055 node->continue_target()->Branch(equal); 2054 node->continue_target()->Branch(equal);
2056 2055
2057 end_del_check.Bind(); 2056 end_del_check.Bind();
2058 // Store the entry in the 'each' expression and take another spin in the loop. 2057 // Store the entry in the 'each' expression and take another spin in the loop.
2059 // edx: i'th entry of the enum cache (or string there of) 2058 // edx: i'th entry of the enum cache (or string there of)
2060 frame_->Push(ebx); 2059 frame_->Push(ebx);
2061 { Reference each(this, node->each()); 2060 { Reference each(this, node->each());
2062 if (!each.is_illegal()) { 2061 if (!each.is_illegal()) {
2063 if (each.size() > 0) { 2062 if (each.size() > 0) {
2064 frame_->Push(frame_->Element(each.size())); 2063 frame_->Push(frame_->ElementAt(each.size()));
2065 } 2064 }
2066 // If the reference was to a slot we rely on the convenient property 2065 // If the reference was to a slot we rely on the convenient property
2067 // that it doesn't matter whether a value (eg, ebx pushed above) is 2066 // that it doesn't matter whether a value (eg, ebx pushed above) is
2068 // right on top of or right underneath a zero-sized reference. 2067 // right on top of or right underneath a zero-sized reference.
2069 each.SetValue(NOT_CONST_INIT); 2068 each.SetValue(NOT_CONST_INIT);
2070 if (each.size() > 0) { 2069 if (each.size() > 0) {
2071 // It's safe to pop the value lying on top of the reference before 2070 // It's safe to pop the value lying on top of the reference before
2072 // unloading the reference itself (which preserves the top of stack, 2071 // unloading the reference itself (which preserves the top of stack,
2073 // ie, now the topmost value of the non-zero sized reference), since 2072 // ie, now the topmost value of the non-zero sized reference), since
2074 // we will discard the top of stack after unloading the reference 2073 // we will discard the top of stack after unloading the reference
2075 // anyway. 2074 // anyway.
2076 frame_->Pop(); 2075 frame_->Drop();
2077 } 2076 }
2078 } 2077 }
2079 } 2078 }
2080 // Discard the i'th entry pushed above or else the remainder of the 2079 // Discard the i'th entry pushed above or else the remainder of the
2081 // reference, whichever is currently on top of the stack. 2080 // reference, whichever is currently on top of the stack.
2082 frame_->Pop(); 2081 frame_->Drop();
2083 2082
2084 // Body. 2083 // Body.
2085 CheckStack(); // TODO(1222600): ignore if body contains calls. 2084 CheckStack(); // TODO(1222600): ignore if body contains calls.
2086 Visit(node->body()); 2085 Visit(node->body());
2087 2086
2088 // Next. 2087 // Next.
2089 node->continue_target()->Bind(); 2088 node->continue_target()->Bind();
2090 frame_->Pop(eax); 2089 frame_->Pop(eax);
2091 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 2090 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
2092 frame_->Push(eax); 2091 frame_->Push(eax);
(...skipping 24 matching lines...) Expand all
2117 // Store the caught exception in the catch variable. 2116 // Store the caught exception in the catch variable.
2118 { Reference ref(this, node->catch_var()); 2117 { Reference ref(this, node->catch_var());
2119 ASSERT(ref.is_slot()); 2118 ASSERT(ref.is_slot());
2120 // Load the exception to the top of the stack. Here we make use of the 2119 // Load the exception to the top of the stack. Here we make use of the
2121 // convenient property that it doesn't matter whether a value is 2120 // convenient property that it doesn't matter whether a value is
2122 // immediately on top of or underneath a zero-sized reference. 2121 // immediately on top of or underneath a zero-sized reference.
2123 ref.SetValue(NOT_CONST_INIT); 2122 ref.SetValue(NOT_CONST_INIT);
2124 } 2123 }
2125 2124
2126 // Remove the exception from the stack. 2125 // Remove the exception from the stack.
2127 frame_->Pop(); 2126 frame_->Drop();
2128 2127
2129 VisitStatements(node->catch_block()->statements()); 2128 VisitStatements(node->catch_block()->statements());
2130 if (frame_ != NULL) { 2129 if (frame_ != NULL) {
2131 exit.Jump(); 2130 exit.Jump();
2132 } 2131 }
2133 2132
2134 2133
2135 // --- Try block --- 2134 // --- Try block ---
2136 try_block.Bind(); 2135 try_block.Bind();
2137 2136
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after
2639 case ObjectLiteral::Property::COMPUTED: { 2638 case ObjectLiteral::Property::COMPUTED: {
2640 Handle<Object> key(property->key()->handle()); 2639 Handle<Object> key(property->key()->handle());
2641 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2640 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
2642 if (key->IsSymbol()) { 2641 if (key->IsSymbol()) {
2643 __ mov(eax, frame_->Top()); 2642 __ mov(eax, frame_->Top());
2644 frame_->Push(eax); 2643 frame_->Push(eax);
2645 Load(property->value()); 2644 Load(property->value());
2646 frame_->Pop(eax); 2645 frame_->Pop(eax);
2647 __ Set(ecx, Immediate(key)); 2646 __ Set(ecx, Immediate(key));
2648 frame_->CallCode(ic, RelocInfo::CODE_TARGET, 0); 2647 frame_->CallCode(ic, RelocInfo::CODE_TARGET, 0);
2649 frame_->Pop(); 2648 frame_->Drop();
2650 // Ignore result. 2649 // Ignore result.
2651 break; 2650 break;
2652 } 2651 }
2653 // Fall through 2652 // Fall through
2654 } 2653 }
2655 case ObjectLiteral::Property::PROTOTYPE: { 2654 case ObjectLiteral::Property::PROTOTYPE: {
2656 __ mov(eax, frame_->Top()); 2655 __ mov(eax, frame_->Top());
2657 frame_->Push(eax); 2656 frame_->Push(eax);
2658 Load(property->key()); 2657 Load(property->key());
2659 Load(property->value()); 2658 Load(property->value());
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
2904 // ------------------------------------------- 2903 // -------------------------------------------
2905 // JavaScript example: 'array[index](1, 2, 3)' 2904 // JavaScript example: 'array[index](1, 2, 3)'
2906 // ------------------------------------------- 2905 // -------------------------------------------
2907 2906
2908 // Load the function to call from the property through a reference. 2907 // Load the function to call from the property through a reference.
2909 Reference ref(this, property); 2908 Reference ref(this, property);
2910 ref.GetValue(NOT_INSIDE_TYPEOF); 2909 ref.GetValue(NOT_INSIDE_TYPEOF);
2911 2910
2912 // Pass receiver to called function. 2911 // Pass receiver to called function.
2913 // The reference's size is non-negative. 2912 // The reference's size is non-negative.
2914 frame_->Push(frame_->Element(ref.size())); 2913 frame_->Push(frame_->ElementAt(ref.size()));
2915 2914
2916 // Call the function. 2915 // Call the function.
2917 CallWithArguments(args, node->position()); 2916 CallWithArguments(args, node->position());
2918 } 2917 }
2919 2918
2920 } else { 2919 } else {
2921 // ---------------------------------- 2920 // ----------------------------------
2922 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 2921 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
2923 // ---------------------------------- 2922 // ----------------------------------
2924 2923
(...skipping 30 matching lines...) Expand all
2955 Load(args->at(i)); 2954 Load(args->at(i));
2956 } 2955 }
2957 2956
2958 // Constructors are called with the number of arguments in register 2957 // Constructors are called with the number of arguments in register
2959 // eax for now. Another option would be to have separate construct 2958 // eax for now. Another option would be to have separate construct
2960 // call trampolines per different arguments counts encountered. 2959 // call trampolines per different arguments counts encountered.
2961 __ Set(eax, Immediate(args->length())); 2960 __ Set(eax, Immediate(args->length()));
2962 2961
2963 // Load the function into temporary function slot as per calling 2962 // Load the function into temporary function slot as per calling
2964 // convention. 2963 // convention.
2965 __ mov(edi, frame_->Element(args->length() + 1)); 2964 __ mov(edi, frame_->ElementAt(args->length() + 1));
2966 2965
2967 // Call the construct call builtin that handles allocation and 2966 // Call the construct call builtin that handles allocation and
2968 // constructor invocation. 2967 // constructor invocation.
2969 __ RecordPosition(node->position()); 2968 __ RecordPosition(node->position());
2970 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); 2969 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
2971 frame_->CallCode(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1); 2970 frame_->CallCode(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1);
2972 // Discard the function and "push" the newly created object. 2971 // Discard the function and "push" the newly created object.
2973 __ mov(frame_->Top(), eax); 2972 __ mov(frame_->Top(), eax);
2974 } 2973 }
2975 2974
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
3167 __ mov(frame_->Top(), eax); 3166 __ mov(frame_->Top(), eax);
3168 leave.Bind(); 3167 leave.Bind();
3169 } 3168 }
3170 3169
3171 3170
3172 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 3171 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
3173 ASSERT(args->length() == 2); 3172 ASSERT(args->length() == 2);
3174 JumpTarget leave(this); 3173 JumpTarget leave(this);
3175 Load(args->at(0)); // Load the object. 3174 Load(args->at(0)); // Load the object.
3176 Load(args->at(1)); // Load the value. 3175 Load(args->at(1)); // Load the value.
3177 __ mov(eax, frame_->Element(1)); 3176 __ mov(eax, frame_->ElementAt(1));
3178 __ mov(ecx, frame_->Top()); 3177 __ mov(ecx, frame_->Top());
3179 // if (object->IsSmi()) return object. 3178 // if (object->IsSmi()) return object.
3180 __ test(eax, Immediate(kSmiTagMask)); 3179 __ test(eax, Immediate(kSmiTagMask));
3181 leave.Branch(zero, taken); 3180 leave.Branch(zero, taken);
3182 // It is a heap object - get map. 3181 // It is a heap object - get map.
3183 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 3182 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
3184 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 3183 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
3185 // if (!object->IsJSValue()) return object. 3184 // if (!object->IsJSValue()) return object.
3186 __ cmp(ebx, JS_VALUE_TYPE); 3185 __ cmp(ebx, JS_VALUE_TYPE);
3187 leave.Branch(not_equal, not_taken); 3186 leave.Branch(not_equal, not_taken);
3188 // Store the value. 3187 // Store the value.
3189 __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx); 3188 __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx);
3190 // Update the write barrier. 3189 // Update the write barrier.
3191 __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx); 3190 __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx);
3192 // Leave. 3191 // Leave.
3193 leave.Bind(); 3192 leave.Bind();
3194 __ mov(ecx, frame_->Top()); 3193 __ mov(ecx, frame_->Top());
3195 frame_->Pop(); 3194 frame_->Drop();
3196 __ mov(frame_->Top(), ecx); 3195 __ mov(frame_->Top(), ecx);
3197 } 3196 }
3198 3197
3199 3198
3200 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 3199 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
3201 ASSERT(args->length() == 1); 3200 ASSERT(args->length() == 1);
3202 3201
3203 // Load the key onto the stack and set register eax to the formal 3202 // Load the key onto the stack and set register eax to the formal
3204 // parameters count for the currently executing function. 3203 // parameters count for the currently executing function.
3205 Load(args->at(0)); 3204 Load(args->at(0));
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
3500 target.GetValue(NOT_INSIDE_TYPEOF); 3499 target.GetValue(NOT_INSIDE_TYPEOF);
3501 3500
3502 CountOperationDeferred* deferred = 3501 CountOperationDeferred* deferred =
3503 new CountOperationDeferred(this, is_postfix, is_increment, 3502 new CountOperationDeferred(this, is_postfix, is_increment,
3504 target.size() * kPointerSize); 3503 target.size() * kPointerSize);
3505 3504
3506 frame_->Pop(eax); // Load TOS into eax for calculations below 3505 frame_->Pop(eax); // Load TOS into eax for calculations below
3507 3506
3508 // Postfix: Store the old value as the result. 3507 // Postfix: Store the old value as the result.
3509 if (is_postfix) { 3508 if (is_postfix) {
3510 __ mov(frame_->Element(target.size()), eax); 3509 __ mov(frame_->ElementAt(target.size()), eax);
3511 } 3510 }
3512 3511
3513 // Perform optimistic increment/decrement. 3512 // Perform optimistic increment/decrement.
3514 if (is_increment) { 3513 if (is_increment) {
3515 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3514 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3516 } else { 3515 } else {
3517 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3516 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3518 } 3517 }
3519 3518
3520 // If the count operation didn't overflow and the result is a 3519 // If the count operation didn't overflow and the result is a
3521 // valid smi, we're done. Otherwise, we jump to the deferred 3520 // valid smi, we're done. Otherwise, we jump to the deferred
3522 // slow-case code. 3521 // slow-case code.
3523 __ j(overflow, deferred->enter(), not_taken); 3522 __ j(overflow, deferred->enter(), not_taken);
3524 __ test(eax, Immediate(kSmiTagMask)); 3523 __ test(eax, Immediate(kSmiTagMask));
3525 __ j(not_zero, deferred->enter(), not_taken); 3524 __ j(not_zero, deferred->enter(), not_taken);
3526 3525
3527 // Store the new value in the target if not const. 3526 // Store the new value in the target if not const.
3528 __ bind(deferred->exit()); 3527 __ bind(deferred->exit());
3529 frame_->Push(eax); // Push the new value to TOS 3528 frame_->Push(eax); // Push the new value to TOS
3530 if (!is_const) target.SetValue(NOT_CONST_INIT); 3529 if (!is_const) target.SetValue(NOT_CONST_INIT);
3531 } 3530 }
3532 3531
3533 // Postfix: Discard the new value and use the old. 3532 // Postfix: Discard the new value and use the old.
3534 if (is_postfix) { 3533 if (is_postfix) {
3535 frame_->Pop(); 3534 frame_->Drop();
3536 } 3535 }
3537 } 3536 }
3538 3537
3539 3538
3540 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 3539 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
3541 // Note that due to an optimization in comparison operations (typeof 3540 // Note that due to an optimization in comparison operations (typeof
3542 // compared to a string literal), we can evaluate a binary expression such 3541 // compared to a string literal), we can evaluate a binary expression such
3543 // as AND or OR and not leave a value on the frame or in the cc register. 3542 // as AND or OR and not leave a value on the frame or in the cc register.
3544 Comment cmnt(masm_, "[ BinaryOperation"); 3543 Comment cmnt(masm_, "[ BinaryOperation");
3545 Token::Value op = node->op(); 3544 Token::Value op = node->op();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3582 // 9.2, page 30. 3581 // 9.2, page 30.
3583 // 3582 //
3584 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3583 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3585 __ mov(eax, frame_->Top()); 3584 __ mov(eax, frame_->Top());
3586 frame_->Push(eax); 3585 frame_->Push(eax);
3587 ToBoolean(&pop_and_continue, &exit); 3586 ToBoolean(&pop_and_continue, &exit);
3588 Branch(false, &exit); 3587 Branch(false, &exit);
3589 3588
3590 // Pop the result of evaluating the first part. 3589 // Pop the result of evaluating the first part.
3591 pop_and_continue.Bind(); 3590 pop_and_continue.Bind();
3592 frame_->Pop(); 3591 frame_->Drop();
3593 3592
3594 // Evaluate right side expression. 3593 // Evaluate right side expression.
3595 is_true.Bind(); 3594 is_true.Bind();
3596 Load(node->right()); 3595 Load(node->right());
3597 3596
3598 // Exit (always with a materialized value). 3597 // Exit (always with a materialized value).
3599 exit.Bind(); 3598 exit.Bind();
3600 } 3599 }
3601 3600
3602 } else if (op == Token::OR) { 3601 } else if (op == Token::OR) {
(...skipping 22 matching lines...) Expand all
3625 // standard ToBoolean() conversion as described in ECMA-262, 3624 // standard ToBoolean() conversion as described in ECMA-262,
3626 // section 9.2, page 30. 3625 // section 9.2, page 30.
3627 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3626 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3628 __ mov(eax, frame_->Top()); 3627 __ mov(eax, frame_->Top());
3629 frame_->Push(eax); 3628 frame_->Push(eax);
3630 ToBoolean(&exit, &pop_and_continue); 3629 ToBoolean(&exit, &pop_and_continue);
3631 Branch(true, &exit); 3630 Branch(true, &exit);
3632 3631
3633 // Pop the result of evaluating the first part. 3632 // Pop the result of evaluating the first part.
3634 pop_and_continue.Bind(); 3633 pop_and_continue.Bind();
3635 frame_->Pop(); 3634 frame_->Drop();
3636 3635
3637 // Evaluate right side expression. 3636 // Evaluate right side expression.
3638 is_false.Bind(); 3637 is_false.Bind();
3639 Load(node->right()); 3638 Load(node->right());
3640 3639
3641 // Exit (always with a materialized value). 3640 // Exit (always with a materialized value).
3642 exit.Bind(); 3641 exit.Bind();
3643 } 3642 }
3644 3643
3645 } else { 3644 } else {
(...skipping 1692 matching lines...) Expand 10 before | Expand all | Expand 10 after
5338 5337
5339 // Slow-case: Go through the JavaScript implementation. 5338 // Slow-case: Go through the JavaScript implementation.
5340 __ bind(&slow); 5339 __ bind(&slow);
5341 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5340 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5342 } 5341 }
5343 5342
5344 5343
5345 #undef __ 5344 #undef __
5346 5345
5347 } } // namespace v8::internal 5346 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/jump-target-ia32.cc » ('j') | src/virtual-frame-ia32.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698