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

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

Issue 6334: Simplify CodeGenerator hierarchy by not using a base class. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 2 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
« no previous file with comments | « src/codegen-ia32.h ('k') | tools/v8.xcodeproj/project.pbxproj » ('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 12 matching lines...) Expand all
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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 "prettyprinter.h"
34 #include "scopeinfo.h"
35 #include "scopes.h" 33 #include "scopes.h"
36 #include "runtime.h" 34 #include "runtime.h"
37 35
38 namespace v8 { namespace internal { 36 namespace v8 { namespace internal {
39 37
40 #define TOS (Operand(esp, 0)) 38 #define TOS (Operand(esp, 0))
41 39
42 40
43 class Ia32CodeGenerator;
44
45 // Mode to overwrite BinaryExpression values.
46 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
47
48
49 // -----------------------------------------------------------------------------
50 // Reference support
51
52 // A reference is a C++ stack-allocated object that keeps an ECMA
53 // reference on the execution stack while in scope. For variables
54 // the reference is empty, indicating that it isn't necessary to
55 // store state on the stack for keeping track of references to those.
56 // For properties, we keep either one (named) or two (indexed) values
57 // on the execution stack to represent the reference.
58
59 enum InitState { CONST_INIT, NOT_CONST_INIT };
60 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
61
62 class Reference BASE_EMBEDDED {
63 public:
64 // The values of the types is important, see size().
65 enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
66 Reference(Ia32CodeGenerator* cgen, Expression* expression);
67 ~Reference();
68
69 Expression* expression() const { return expression_; }
70 Type type() const { return type_; }
71 void set_type(Type value) {
72 ASSERT(type_ == ILLEGAL);
73 type_ = value;
74 }
75
76 // The size of the reference or -1 if the reference is illegal.
77 int size() const { return type_; }
78
79 bool is_illegal() const { return type_ == ILLEGAL; }
80 bool is_slot() const { return type_ == SLOT; }
81 bool is_property() const { return type_ == NAMED || type_ == KEYED; }
82
83 // Return the name. Only valid for named property references.
84 Handle<String> GetName();
85
86 // Generate code to push the value of the reference on top of the
87 // expression stack. The reference is expected to be already on top of
88 // the expression stack, and it is left in place with its value above it.
89 void GetValue(TypeofState typeof_state);
90
91 // Generate code to store the value on top of the expression stack in the
92 // reference. The reference is expected to be immediately below the value
93 // on the expression stack. The stored value is left in place (with the
94 // reference intact below it) to support chained assignments.
95 void SetValue(InitState init_state);
96
97 private:
98 Ia32CodeGenerator* cgen_;
99 Expression* expression_;
100 Type type_;
101 };
102
103
104 // -------------------------------------------------------------------------
105 // Code generation state
106
107 // The state is passed down the AST by the code generator (and back up, in
108 // the form of the state of the label pair). It is threaded through the
109 // call stack. Constructing a state implicitly pushes it on the owning code
110 // generator's stack of states, and destroying one implicitly pops it.
111
112 class CodeGenState BASE_EMBEDDED {
113 public:
114 // Create an initial code generator state. Destroying the initial state
115 // leaves the code generator with a NULL state.
116 explicit CodeGenState(Ia32CodeGenerator* owner);
117
118 // Create a code generator state based on a code generator's current
119 // state. The new state has its own typeof state and pair of branch
120 // labels.
121 CodeGenState(Ia32CodeGenerator* owner,
122 TypeofState typeof_state,
123 Label* true_target,
124 Label* false_target);
125
126 // Destroy a code generator state and restore the owning code generator's
127 // previous state.
128 ~CodeGenState();
129
130 TypeofState typeof_state() const { return typeof_state_; }
131 Label* true_target() const { return true_target_; }
132 Label* false_target() const { return false_target_; }
133
134 private:
135 Ia32CodeGenerator* owner_;
136 TypeofState typeof_state_;
137 Label* true_target_;
138 Label* false_target_;
139 CodeGenState* previous_;
140 };
141
142
143 // -----------------------------------------------------------------------------
144 // Ia32CodeGenerator
145
146 class Ia32CodeGenerator: public CodeGenerator {
147 public:
148 static Handle<Code> MakeCode(FunctionLiteral* fun,
149 Handle<Script> script,
150 bool is_eval);
151
152 MacroAssembler* masm() { return masm_; }
153
154 Scope* scope() const { return scope_; }
155
156 CodeGenState* state() { return state_; }
157 void set_state(CodeGenState* state) { state_ = state; }
158
159 private:
160 // Assembler
161 MacroAssembler* masm_; // to generate code
162
163 // Code generation state
164 Scope* scope_;
165 Condition cc_reg_;
166 CodeGenState* state_;
167 bool is_inside_try_;
168 int break_stack_height_;
169
170 // Labels
171 Label function_return_;
172
173 // Construction/destruction
174 Ia32CodeGenerator(int buffer_size,
175 Handle<Script> script,
176 bool is_eval);
177 virtual ~Ia32CodeGenerator() { delete masm_; }
178
179 // Main code generation function
180 void GenCode(FunctionLiteral* fun);
181
182 // The following are used by class Reference.
183 void LoadReference(Reference* ref);
184 void UnloadReference(Reference* ref);
185
186 // State
187 bool has_cc() const { return cc_reg_ >= 0; }
188 TypeofState typeof_state() const { return state_->typeof_state(); }
189 Label* true_target() const { return state_->true_target(); }
190 Label* false_target() const { return state_->false_target(); }
191
192 // Expressions
193 Operand GlobalObject() const {
194 return ContextOperand(esi, Context::GLOBAL_INDEX);
195 }
196
197 // Support functions for accessing parameters.
198 Operand ParameterOperand(int index) const {
199 int num_parameters = scope()->num_parameters();
200 ASSERT(-2 <= index && index < num_parameters);
201 return Operand(ebp, (1 + num_parameters - index) * kPointerSize);
202 }
203
204 Operand ReceiverOperand() const { return ParameterOperand(-1); }
205
206 Operand FunctionOperand() const {
207 return Operand(ebp, JavaScriptFrameConstants::kFunctionOffset);
208 }
209
210 Operand ContextOperand(Register context, int index) const {
211 return Operand(context, Context::SlotOffset(index));
212 }
213
214 Operand SlotOperand(Slot* slot, Register tmp);
215
216 void LoadCondition(Expression* x,
217 TypeofState typeof_state,
218 Label* true_target,
219 Label* false_target,
220 bool force_cc);
221 void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
222 void LoadGlobal();
223
224 // Read a value from a slot and leave it on top of the expression stack.
225 void LoadFromSlot(Slot* slot, TypeofState typeof_state);
226
227 // Special code for typeof expressions: Unfortunately, we must
228 // be careful when loading the expression in 'typeof'
229 // expressions. We are not allowed to throw reference errors for
230 // non-existing properties of the global object, so we must make it
231 // look like an explicit property access, instead of an access
232 // through the context chain.
233 void LoadTypeofExpression(Expression* x);
234
235 void ToBoolean(Label* true_target, Label* false_target);
236
237 void GenericBinaryOperation(
238 Token::Value op,
239 const OverwriteMode overwrite_mode = NO_OVERWRITE);
240 void Comparison(Condition cc, bool strict = false);
241
242 // Inline small integer literals. To prevent long attacker-controlled byte
243 // sequences, we only inline small Smi:s.
244 static const int kMaxSmiInlinedBits = 16;
245 bool IsInlineSmi(Literal* literal);
246 void SmiComparison(Condition cc, Handle<Object> value, bool strict = false);
247 void SmiOperation(Token::Value op,
248 Handle<Object> value,
249 bool reversed,
250 OverwriteMode overwrite_mode);
251
252 void CallWithArguments(ZoneList<Expression*>* arguments, int position);
253
254 // Declare global variables and functions in the given array of
255 // name/value pairs.
256 virtual void DeclareGlobals(Handle<FixedArray> pairs);
257
258 // Instantiate the function boilerplate.
259 void InstantiateBoilerplate(Handle<JSFunction> boilerplate);
260
261 // Control flow
262 void Branch(bool if_true, Label* L);
263 void CheckStack();
264 void CleanStack(int num_bytes);
265
266 // Node visitors
267 #define DEF_VISIT(type) \
268 virtual void Visit##type(type* node);
269 NODE_LIST(DEF_VISIT)
270 #undef DEF_VISIT
271
272 // Only allow fast-case switch if the range of labels is at most
273 // this factor times the number of case labels.
274 // Value is derived from comparing the size of code generated by the normal
275 // switch code for Smi-labels to the size of a single pointer. If code
276 // quality increases this number should be decreased to match.
277 static const int kFastSwitchMaxOverheadFactor = 5;
278
279 // Minimal number of switch cases required before we allow jump-table
280 // optimization.
281 static const int kFastSwitchMinCaseCount = 5;
282
283 virtual int FastCaseSwitchMaxOverheadFactor();
284 virtual int FastCaseSwitchMinCaseCount();
285
286 // Generate a computed jump with an empty jump table.
287 // Binds a label to the start of the jump table. This table must
288 // be populated later when the addresses of the targets are known.
289 // Used by GenerateFastCaseSwitchStatement.
290 virtual void GenerateFastCaseSwitchJumpTable(
291 SwitchStatement* node, int min_index, int range, Label *fail_label,
292 SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels);
293
294 void RecordStatementPosition(Node* node);
295
296 // Activation frames.
297 void EnterJSFrame();
298 void ExitJSFrame();
299
300 virtual void GenerateIsSmi(ZoneList<Expression*>* args);
301 virtual void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
302 virtual void GenerateIsArray(ZoneList<Expression*>* args);
303
304 virtual void GenerateArgumentsLength(ZoneList<Expression*>* args);
305 virtual void GenerateArgumentsAccess(ZoneList<Expression*>* args);
306
307 virtual void GenerateValueOf(ZoneList<Expression*>* args);
308 virtual void GenerateSetValueOf(ZoneList<Expression*>* args);
309
310 virtual void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
311
312 virtual void GenerateObjectEquals(ZoneList<Expression*>* args);
313
314 friend class Reference;
315 friend class Property;
316 friend class VariableProxy;
317 friend class Slot;
318 };
319
320
321 // ------------------------------------------------------------------------- 41 // -------------------------------------------------------------------------
322 // CodeGenState implementation. 42 // CodeGenState implementation.
323 43
324 CodeGenState::CodeGenState(Ia32CodeGenerator* owner) 44 CodeGenState::CodeGenState(CodeGenerator* owner)
325 : owner_(owner), 45 : owner_(owner),
326 typeof_state_(NOT_INSIDE_TYPEOF), 46 typeof_state_(NOT_INSIDE_TYPEOF),
327 true_target_(NULL), 47 true_target_(NULL),
328 false_target_(NULL), 48 false_target_(NULL),
329 previous_(NULL) { 49 previous_(NULL) {
330 owner_->set_state(this); 50 owner_->set_state(this);
331 } 51 }
332 52
333 53
334 CodeGenState::CodeGenState(Ia32CodeGenerator* owner, 54 CodeGenState::CodeGenState(CodeGenerator* owner,
335 TypeofState typeof_state, 55 TypeofState typeof_state,
336 Label* true_target, 56 Label* true_target,
337 Label* false_target) 57 Label* false_target)
338 : owner_(owner), 58 : owner_(owner),
339 typeof_state_(typeof_state), 59 typeof_state_(typeof_state),
340 true_target_(true_target), 60 true_target_(true_target),
341 false_target_(false_target), 61 false_target_(false_target),
342 previous_(owner->state()) { 62 previous_(owner->state()) {
343 owner_->set_state(this); 63 owner_->set_state(this);
344 } 64 }
345 65
346 66
347 CodeGenState::~CodeGenState() { 67 CodeGenState::~CodeGenState() {
348 ASSERT(owner_->state() == this); 68 ASSERT(owner_->state() == this);
349 owner_->set_state(previous_); 69 owner_->set_state(previous_);
350 } 70 }
351 71
352 72
353 // ----------------------------------------------------------------------------- 73 // -----------------------------------------------------------------------------
354 // Ia32CodeGenerator implementation 74 // CodeGenerator implementation
355 75
356 #define __ masm_-> 76 #define __ masm_->
357 77
358 Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit, 78 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
359 Handle<Script> script, 79 bool is_eval)
360 bool is_eval) { 80 : is_eval_(is_eval),
361 #ifdef ENABLE_DISASSEMBLER 81 script_(script),
362 bool print_code = FLAG_print_code && !Bootstrapper::IsActive(); 82 deferred_(8),
363 #endif
364
365 #ifdef DEBUG
366 bool print_source = false;
367 bool print_ast = false;
368 const char* ftype;
369
370 if (Bootstrapper::IsActive()) {
371 print_source = FLAG_print_builtin_source;
372 print_ast = FLAG_print_builtin_ast;
373 print_code = FLAG_print_builtin_code;
374 ftype = "builtin";
375 } else {
376 print_source = FLAG_print_source;
377 print_ast = FLAG_print_ast;
378 ftype = "user-defined";
379 }
380
381 if (FLAG_trace_codegen || print_source || print_ast) {
382 PrintF("*** Generate code for %s function: ", ftype);
383 flit->name()->ShortPrint();
384 PrintF(" ***\n");
385 }
386
387 if (print_source) {
388 PrintF("--- Source from AST ---\n%s\n", PrettyPrinter().PrintProgram(flit));
389 }
390
391 if (print_ast) {
392 PrintF("--- AST ---\n%s\n", AstPrinter().PrintProgram(flit));
393 }
394 #endif // DEBUG
395
396 // Generate code.
397 const int initial_buffer_size = 4 * KB;
398 Ia32CodeGenerator cgen(initial_buffer_size, script, is_eval);
399 cgen.GenCode(flit);
400 if (cgen.HasStackOverflow()) {
401 ASSERT(!Top::has_pending_exception());
402 return Handle<Code>::null();
403 }
404
405 // Process any deferred code.
406 cgen.ProcessDeferred();
407
408 // Allocate and install the code.
409 CodeDesc desc;
410 cgen.masm()->GetCode(&desc);
411 ScopeInfo<> sinfo(flit->scope());
412 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
413 Handle<Code> code = Factory::NewCode(desc, &sinfo, flags);
414
415 // Add unresolved entries in the code to the fixup list.
416 Bootstrapper::AddFixup(*code, cgen.masm());
417
418 #ifdef ENABLE_DISASSEMBLER
419 if (print_code) {
420 // Print the source code if available.
421 if (!script->IsUndefined() && !script->source()->IsUndefined()) {
422 PrintF("--- Raw source ---\n");
423 StringInputBuffer stream(String::cast(script->source()));
424 stream.Seek(flit->start_position());
425 // flit->end_position() points to the last character in the stream. We
426 // need to compensate by adding one to calculate the length.
427 int source_len = flit->end_position() - flit->start_position() + 1;
428 for (int i = 0; i < source_len; i++) {
429 if (stream.has_more()) PrintF("%c", stream.GetNext());
430 }
431 PrintF("\n\n");
432 }
433 PrintF("--- Code ---\n");
434 code->Disassemble();
435 }
436 #endif // ENABLE_DISASSEMBLER
437
438 return code;
439 }
440
441
442 Ia32CodeGenerator::Ia32CodeGenerator(int buffer_size,
443 Handle<Script> script,
444 bool is_eval)
445 : CodeGenerator(is_eval, script),
446 masm_(new MacroAssembler(NULL, buffer_size)), 83 masm_(new MacroAssembler(NULL, buffer_size)),
447 scope_(NULL), 84 scope_(NULL),
448 cc_reg_(no_condition), 85 cc_reg_(no_condition),
449 state_(NULL), 86 state_(NULL),
450 is_inside_try_(false), 87 is_inside_try_(false),
451 break_stack_height_(0) { 88 break_stack_height_(0) {
452 } 89 }
453 90
454 91
455 // Calling conventions: 92 // Calling conventions:
456 // ebp: frame pointer 93 // ebp: frame pointer
457 // esp: stack pointer 94 // esp: stack pointer
458 // edi: caller's parameter pointer 95 // edi: caller's parameter pointer
459 // esi: callee's context 96 // esi: callee's context
460 97
461 void Ia32CodeGenerator::GenCode(FunctionLiteral* fun) { 98 void CodeGenerator::GenCode(FunctionLiteral* fun) {
462 // Record the position for debugging purposes. 99 // Record the position for debugging purposes.
463 __ RecordPosition(fun->start_position()); 100 __ RecordPosition(fun->start_position());
464 101
465 Scope* scope = fun->scope(); 102 Scope* scope = fun->scope();
466 ZoneList<Statement*>* body = fun->body(); 103 ZoneList<Statement*>* body = fun->body();
467 104
468 // Initialize state. 105 // Initialize state.
469 { CodeGenState state(this); 106 { CodeGenState state(this);
470 scope_ = scope; 107 scope_ = scope;
471 cc_reg_ = no_condition; 108 cc_reg_ = no_condition;
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 } 299 }
663 } 300 }
664 301
665 // Code generation state must be reset. 302 // Code generation state must be reset.
666 scope_ = NULL; 303 scope_ = NULL;
667 ASSERT(!has_cc()); 304 ASSERT(!has_cc());
668 ASSERT(state_ == NULL); 305 ASSERT(state_ == NULL);
669 } 306 }
670 307
671 308
672 Operand Ia32CodeGenerator::SlotOperand(Slot* slot, Register tmp) { 309 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
673 // Currently, this assertion will fail if we try to assign to 310 // Currently, this assertion will fail if we try to assign to
674 // a constant variable that is constant because it is read-only 311 // a constant variable that is constant because it is read-only
675 // (such as the variable referring to a named function expression). 312 // (such as the variable referring to a named function expression).
676 // We need to implement assignments to read-only variables. 313 // We need to implement assignments to read-only variables.
677 // Ideally, we should do this during AST generation (by converting 314 // Ideally, we should do this during AST generation (by converting
678 // such assignments into expression statements); however, in general 315 // such assignments into expression statements); however, in general
679 // we may not be able to make the decision until past AST generation, 316 // we may not be able to make the decision until past AST generation,
680 // that is when the entire program is known. 317 // that is when the entire program is known.
681 ASSERT(slot != NULL); 318 ASSERT(slot != NULL);
682 int index = slot->index(); 319 int index = slot->index();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 return Operand(eax); 358 return Operand(eax);
722 } 359 }
723 } 360 }
724 361
725 362
726 // Loads a value on TOS. If it is a boolean value, the result may have been 363 // Loads a value on TOS. If it is a boolean value, the result may have been
727 // (partially) translated into branches, or it may have set the condition code 364 // (partially) translated into branches, or it may have set the condition code
728 // register. If force_cc is set, the value is forced to set the condition code 365 // register. If force_cc is set, the value is forced to set the condition code
729 // register and no value is pushed. If the condition code register was set, 366 // register and no value is pushed. If the condition code register was set,
730 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. 367 // has_cc() is true and cc_reg_ contains the condition to test for 'true'.
731 void Ia32CodeGenerator::LoadCondition(Expression* x, 368 void CodeGenerator::LoadCondition(Expression* x,
732 TypeofState typeof_state, 369 TypeofState typeof_state,
733 Label* true_target, 370 Label* true_target,
734 Label* false_target, 371 Label* false_target,
735 bool force_cc) { 372 bool force_cc) {
736 ASSERT(!has_cc()); 373 ASSERT(!has_cc());
737 374
738 { CodeGenState new_state(this, typeof_state, true_target, false_target); 375 { CodeGenState new_state(this, typeof_state, true_target, false_target);
739 Visit(x); 376 Visit(x);
740 } 377 }
741 if (force_cc && !has_cc()) { 378 if (force_cc && !has_cc()) {
742 ToBoolean(true_target, false_target); 379 ToBoolean(true_target, false_target);
743 } 380 }
744 ASSERT(has_cc() || !force_cc); 381 ASSERT(has_cc() || !force_cc);
745 } 382 }
746 383
747 384
748 void Ia32CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 385 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
749 Label true_target; 386 Label true_target;
750 Label false_target; 387 Label false_target;
751 LoadCondition(x, typeof_state, &true_target, &false_target, false); 388 LoadCondition(x, typeof_state, &true_target, &false_target, false);
752 389
753 if (has_cc()) { 390 if (has_cc()) {
754 // convert cc_reg_ into a bool 391 // convert cc_reg_ into a bool
755 392
756 Label loaded, materialize_true; 393 Label loaded, materialize_true;
757 __ j(cc_reg_, &materialize_true); 394 __ j(cc_reg_, &materialize_true);
758 __ push(Immediate(Factory::false_value())); 395 __ push(Immediate(Factory::false_value()));
(...skipping 25 matching lines...) Expand all
784 __ bind(&false_target); 421 __ bind(&false_target);
785 __ push(Immediate(Factory::false_value())); 422 __ push(Immediate(Factory::false_value()));
786 } 423 }
787 // everything is loaded at this point 424 // everything is loaded at this point
788 __ bind(&loaded); 425 __ bind(&loaded);
789 } 426 }
790 ASSERT(!has_cc()); 427 ASSERT(!has_cc());
791 } 428 }
792 429
793 430
794 void Ia32CodeGenerator::LoadGlobal() { 431 void CodeGenerator::LoadGlobal() {
795 __ push(GlobalObject()); 432 __ push(GlobalObject());
796 } 433 }
797 434
798 435
799 // TODO(1241834): Get rid of this function in favor of just using Load, now 436 // TODO(1241834): Get rid of this function in favor of just using Load, now
800 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global 437 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global
801 // variables w/o reference errors elsewhere. 438 // variables w/o reference errors elsewhere.
802 void Ia32CodeGenerator::LoadTypeofExpression(Expression* x) { 439 void CodeGenerator::LoadTypeofExpression(Expression* x) {
803 Variable* variable = x->AsVariableProxy()->AsVariable(); 440 Variable* variable = x->AsVariableProxy()->AsVariable();
804 if (variable != NULL && !variable->is_this() && variable->is_global()) { 441 if (variable != NULL && !variable->is_this() && variable->is_global()) {
805 // NOTE: This is somewhat nasty. We force the compiler to load 442 // NOTE: This is somewhat nasty. We force the compiler to load
806 // the variable as if through '<global>.<variable>' to make sure we 443 // the variable as if through '<global>.<variable>' to make sure we
807 // do not get reference errors. 444 // do not get reference errors.
808 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); 445 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
809 Literal key(variable->name()); 446 Literal key(variable->name());
810 // TODO(1241834): Fetch the position from the variable instead of using 447 // TODO(1241834): Fetch the position from the variable instead of using
811 // no position. 448 // no position.
812 Property property(&global, &key, RelocInfo::kNoPosition); 449 Property property(&global, &key, RelocInfo::kNoPosition);
813 Load(&property); 450 Load(&property);
814 } else { 451 } else {
815 Load(x, INSIDE_TYPEOF); 452 Load(x, INSIDE_TYPEOF);
816 } 453 }
817 } 454 }
818 455
819 456
820 Reference::Reference(Ia32CodeGenerator* cgen, Expression* expression) 457 Reference::Reference(CodeGenerator* cgen, Expression* expression)
821 : cgen_(cgen), expression_(expression), type_(ILLEGAL) { 458 : cgen_(cgen), expression_(expression), type_(ILLEGAL) {
822 cgen->LoadReference(this); 459 cgen->LoadReference(this);
823 } 460 }
824 461
825 462
826 Reference::~Reference() { 463 Reference::~Reference() {
827 cgen_->UnloadReference(this); 464 cgen_->UnloadReference(this);
828 } 465 }
829 466
830 467
831 void Ia32CodeGenerator::LoadReference(Reference* ref) { 468 void CodeGenerator::LoadReference(Reference* ref) {
832 Comment cmnt(masm_, "[ LoadReference"); 469 Comment cmnt(masm_, "[ LoadReference");
833 Expression* e = ref->expression(); 470 Expression* e = ref->expression();
834 Property* property = e->AsProperty(); 471 Property* property = e->AsProperty();
835 Variable* var = e->AsVariableProxy()->AsVariable(); 472 Variable* var = e->AsVariableProxy()->AsVariable();
836 473
837 if (property != NULL) { 474 if (property != NULL) {
838 // The expression is either a property or a variable proxy that rewrites 475 // The expression is either a property or a variable proxy that rewrites
839 // to a property. 476 // to a property.
840 Load(property->obj()); 477 Load(property->obj());
841 // We use a named reference if the key is a literal symbol, unless it is 478 // We use a named reference if the key is a literal symbol, unless it is
(...skipping 21 matching lines...) Expand all
863 ref->set_type(Reference::SLOT); 500 ref->set_type(Reference::SLOT);
864 } 501 }
865 } else { 502 } else {
866 // Anything else is a runtime error. 503 // Anything else is a runtime error.
867 Load(e); 504 Load(e);
868 __ CallRuntime(Runtime::kThrowReferenceError, 1); 505 __ CallRuntime(Runtime::kThrowReferenceError, 1);
869 } 506 }
870 } 507 }
871 508
872 509
873 void Ia32CodeGenerator::UnloadReference(Reference* ref) { 510 void CodeGenerator::UnloadReference(Reference* ref) {
874 // Pop a reference from the stack while preserving TOS. 511 // Pop a reference from the stack while preserving TOS.
875 Comment cmnt(masm_, "[ UnloadReference"); 512 Comment cmnt(masm_, "[ UnloadReference");
876 int size = ref->size(); 513 int size = ref->size();
877 if (size <= 0) { 514 if (size <= 0) {
878 // Do nothing. No popping is necessary. 515 // Do nothing. No popping is necessary.
879 } else if (size == 1) { 516 } else if (size == 1) {
880 __ pop(eax); 517 __ pop(eax);
881 __ mov(TOS, eax); 518 __ mov(TOS, eax);
882 } else { 519 } else {
883 __ pop(eax); 520 __ pop(eax);
(...skipping 11 matching lines...) Expand all
895 532
896 private: 533 private:
897 Major MajorKey() { return ToBoolean; } 534 Major MajorKey() { return ToBoolean; }
898 int MinorKey() { return 0; } 535 int MinorKey() { return 0; }
899 }; 536 };
900 537
901 538
902 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and 539 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and
903 // convert it to a boolean in the condition code register or jump to 540 // convert it to a boolean in the condition code register or jump to
904 // 'false_target'/'true_target' as appropriate. 541 // 'false_target'/'true_target' as appropriate.
905 void Ia32CodeGenerator::ToBoolean(Label* true_target, Label* false_target) { 542 void CodeGenerator::ToBoolean(Label* true_target, Label* false_target) {
906 Comment cmnt(masm_, "[ ToBoolean"); 543 Comment cmnt(masm_, "[ ToBoolean");
907 544
908 // The value to convert should be popped from the stack. 545 // The value to convert should be popped from the stack.
909 __ pop(eax); 546 __ pop(eax);
910 547
911 // Fast case checks. 548 // Fast case checks.
912 549
913 // 'false' => false. 550 // 'false' => false.
914 __ cmp(eax, Factory::false_value()); 551 __ cmp(eax, Factory::false_value());
915 __ j(equal, false_target); 552 __ j(equal, false_target);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND"; 643 case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND";
1007 case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR"; 644 case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR";
1008 case Token::SAR: return "GenericBinaryOpStub_SAR"; 645 case Token::SAR: return "GenericBinaryOpStub_SAR";
1009 case Token::SHL: return "GenericBinaryOpStub_SHL"; 646 case Token::SHL: return "GenericBinaryOpStub_SHL";
1010 case Token::SHR: return "GenericBinaryOpStub_SHR"; 647 case Token::SHR: return "GenericBinaryOpStub_SHR";
1011 default: return "GenericBinaryOpStub"; 648 default: return "GenericBinaryOpStub";
1012 } 649 }
1013 } 650 }
1014 651
1015 652
1016 void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op, 653 void CodeGenerator::GenericBinaryOperation(Token::Value op,
1017 OverwriteMode overwrite_mode) { 654 OverwriteMode overwrite_mode) {
1018 Comment cmnt(masm_, "[ BinaryOperation"); 655 Comment cmnt(masm_, "[ BinaryOperation");
1019 Comment cmnt_token(masm_, Token::String(op)); 656 Comment cmnt_token(masm_, Token::String(op));
1020 switch (op) { 657 switch (op) {
1021 case Token::ADD: 658 case Token::ADD:
1022 case Token::SUB: 659 case Token::SUB:
1023 case Token::MUL: 660 case Token::MUL:
1024 case Token::DIV: 661 case Token::DIV:
1025 case Token::MOD: { 662 case Token::MOD: {
1026 GenericBinaryOpStub stub(op, overwrite_mode); 663 GenericBinaryOpStub stub(op, overwrite_mode);
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_); 900 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_);
1264 __ CallStub(&igostub); 901 __ CallStub(&igostub);
1265 } 902 }
1266 903
1267 private: 904 private:
1268 Register tos_reg_; 905 Register tos_reg_;
1269 OverwriteMode overwrite_mode_; 906 OverwriteMode overwrite_mode_;
1270 }; 907 };
1271 908
1272 909
1273 void Ia32CodeGenerator::SmiOperation(Token::Value op, 910 void CodeGenerator::SmiOperation(Token::Value op,
1274 Handle<Object> value, 911 Handle<Object> value,
1275 bool reversed, 912 bool reversed,
1276 OverwriteMode overwrite_mode) { 913 OverwriteMode overwrite_mode) {
1277 // NOTE: This is an attempt to inline (a bit) more of the code for 914 // NOTE: This is an attempt to inline (a bit) more of the code for
1278 // some possible smi operations (like + and -) when (at least) one 915 // some possible smi operations (like + and -) when (at least) one
1279 // of the operands is a literal smi. With this optimization, the 916 // of the operands is a literal smi. With this optimization, the
1280 // performance of the system is increased by ~15%, and the generated 917 // performance of the system is increased by ~15%, and the generated
1281 // code size is increased by ~1% (measured on a combination of 918 // code size is increased by ~1% (measured on a combination of
1282 // different benchmarks). 919 // different benchmarks).
1283 920
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 #ifdef DEBUG 1106 #ifdef DEBUG
1470 void Print() { 1107 void Print() {
1471 PrintF("CompareStub (cc %d), (strict %s)\n", 1108 PrintF("CompareStub (cc %d), (strict %s)\n",
1472 static_cast<int>(cc_), 1109 static_cast<int>(cc_),
1473 strict_ ? "true" : "false"); 1110 strict_ ? "true" : "false");
1474 } 1111 }
1475 #endif 1112 #endif
1476 }; 1113 };
1477 1114
1478 1115
1479 void Ia32CodeGenerator::Comparison(Condition cc, bool strict) { 1116 void CodeGenerator::Comparison(Condition cc, bool strict) {
1480 // Strict only makes sense for equality comparisons. 1117 // Strict only makes sense for equality comparisons.
1481 ASSERT(!strict || cc == equal); 1118 ASSERT(!strict || cc == equal);
1482 1119
1483 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 1120 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
1484 if (cc == greater || cc == less_equal) { 1121 if (cc == greater || cc == less_equal) {
1485 cc = ReverseCondition(cc); 1122 cc = ReverseCondition(cc);
1486 __ pop(edx); 1123 __ pop(edx);
1487 __ pop(eax); 1124 __ pop(eax);
1488 } else { 1125 } else {
1489 __ pop(eax); 1126 __ pop(eax);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1536 CompareStub stub(cc_, strict_); 1173 CompareStub stub(cc_, strict_);
1537 // Setup parameters and call stub. 1174 // Setup parameters and call stub.
1538 __ mov(edx, Operand(eax)); 1175 __ mov(edx, Operand(eax));
1539 __ mov(Operand(eax), Immediate(Smi::FromInt(value_))); 1176 __ mov(Operand(eax), Immediate(Smi::FromInt(value_)));
1540 __ CallStub(&stub); 1177 __ CallStub(&stub);
1541 __ cmp(eax, 0); 1178 __ cmp(eax, 0);
1542 // "result" is returned in the flags 1179 // "result" is returned in the flags
1543 } 1180 }
1544 1181
1545 1182
1546 void Ia32CodeGenerator::SmiComparison(Condition cc, 1183 void CodeGenerator::SmiComparison(Condition cc,
1547 Handle<Object> value, 1184 Handle<Object> value,
1548 bool strict) { 1185 bool strict) {
1549 // Strict only makes sense for equality comparisons. 1186 // Strict only makes sense for equality comparisons.
1550 ASSERT(!strict || cc == equal); 1187 ASSERT(!strict || cc == equal);
1551 1188
1552 int int_value = Smi::cast(*value)->value(); 1189 int int_value = Smi::cast(*value)->value();
1553 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); 1190 ASSERT(is_intn(int_value, kMaxSmiInlinedBits));
1554 1191
1555 SmiComparisonDeferred* deferred = 1192 SmiComparisonDeferred* deferred =
1556 new SmiComparisonDeferred(this, cc, strict, int_value); 1193 new SmiComparisonDeferred(this, cc, strict, int_value);
(...skipping 20 matching lines...) Expand all
1577 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } 1214 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
1578 #endif 1215 #endif
1579 1216
1580 Major MajorKey() { return CallFunction; } 1217 Major MajorKey() { return CallFunction; }
1581 int MinorKey() { return argc_; } 1218 int MinorKey() { return argc_; }
1582 }; 1219 };
1583 1220
1584 1221
1585 // Call the function just below TOS on the stack with the given 1222 // Call the function just below TOS on the stack with the given
1586 // arguments. The receiver is the TOS. 1223 // arguments. The receiver is the TOS.
1587 void Ia32CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 1224 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
1588 int position) { 1225 int position) {
1589 // Push the arguments ("left-to-right") on the stack. 1226 // Push the arguments ("left-to-right") on the stack.
1590 for (int i = 0; i < args->length(); i++) { 1227 for (int i = 0; i < args->length(); i++) {
1591 Load(args->at(i)); 1228 Load(args->at(i));
1592 } 1229 }
1593 1230
1594 // Record the position for debugging purposes. 1231 // Record the position for debugging purposes.
1595 __ RecordPosition(position); 1232 __ RecordPosition(position);
1596 1233
1597 // Use the shared code stub to call the function. 1234 // Use the shared code stub to call the function.
1598 CallFunctionStub call_function(args->length()); 1235 CallFunctionStub call_function(args->length());
1599 __ CallStub(&call_function); 1236 __ CallStub(&call_function);
1600 1237
1601 // Restore context and pop function from the stack. 1238 // Restore context and pop function from the stack.
1602 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1239 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1603 __ mov(TOS, eax); 1240 __ mov(TOS, eax);
1604 } 1241 }
1605 1242
1606 1243
1607 void Ia32CodeGenerator::Branch(bool if_true, Label* L) { 1244 void CodeGenerator::Branch(bool if_true, Label* L) {
1608 ASSERT(has_cc()); 1245 ASSERT(has_cc());
1609 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); 1246 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_);
1610 __ j(cc, L); 1247 __ j(cc, L);
1611 cc_reg_ = no_condition; 1248 cc_reg_ = no_condition;
1612 } 1249 }
1613 1250
1614 1251
1615 void Ia32CodeGenerator::CheckStack() { 1252 void CodeGenerator::CheckStack() {
1616 if (FLAG_check_stack) { 1253 if (FLAG_check_stack) {
1617 Label stack_is_ok; 1254 Label stack_is_ok;
1618 StackCheckStub stub; 1255 StackCheckStub stub;
1619 ExternalReference stack_guard_limit = 1256 ExternalReference stack_guard_limit =
1620 ExternalReference::address_of_stack_guard_limit(); 1257 ExternalReference::address_of_stack_guard_limit();
1621 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); 1258 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
1622 __ j(above_equal, &stack_is_ok, taken); 1259 __ j(above_equal, &stack_is_ok, taken);
1623 __ CallStub(&stub); 1260 __ CallStub(&stub);
1624 __ bind(&stack_is_ok); 1261 __ bind(&stack_is_ok);
1625 } 1262 }
1626 } 1263 }
1627 1264
1628 1265
1629 void Ia32CodeGenerator::VisitBlock(Block* node) { 1266 void CodeGenerator::VisitBlock(Block* node) {
1630 Comment cmnt(masm_, "[ Block"); 1267 Comment cmnt(masm_, "[ Block");
1631 RecordStatementPosition(node); 1268 RecordStatementPosition(node);
1632 node->set_break_stack_height(break_stack_height_); 1269 node->set_break_stack_height(break_stack_height_);
1633 VisitStatements(node->statements()); 1270 VisitStatements(node->statements());
1634 __ bind(node->break_target()); 1271 __ bind(node->break_target());
1635 } 1272 }
1636 1273
1637 1274
1638 void Ia32CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1275 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1639 __ push(Immediate(pairs)); 1276 __ push(Immediate(pairs));
1640 __ push(Operand(esi)); 1277 __ push(Operand(esi));
1641 __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 1278 __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
1642 __ CallRuntime(Runtime::kDeclareGlobals, 3); 1279 __ CallRuntime(Runtime::kDeclareGlobals, 3);
1643 // Return value is ignored. 1280 // Return value is ignored.
1644 } 1281 }
1645 1282
1646 1283
1647 void Ia32CodeGenerator::VisitDeclaration(Declaration* node) { 1284 void CodeGenerator::VisitDeclaration(Declaration* node) {
1648 Comment cmnt(masm_, "[ Declaration"); 1285 Comment cmnt(masm_, "[ Declaration");
1649 Variable* var = node->proxy()->var(); 1286 Variable* var = node->proxy()->var();
1650 ASSERT(var != NULL); // must have been resolved 1287 ASSERT(var != NULL); // must have been resolved
1651 Slot* slot = var->slot(); 1288 Slot* slot = var->slot();
1652 1289
1653 // If it was not possible to allocate the variable at compile time, 1290 // If it was not possible to allocate the variable at compile time,
1654 // we need to "declare" it at runtime to make sure it actually 1291 // we need to "declare" it at runtime to make sure it actually
1655 // exists in the local context. 1292 // exists in the local context.
1656 if (slot != NULL && slot->type() == Slot::LOOKUP) { 1293 if (slot != NULL && slot->type() == Slot::LOOKUP) {
1657 // Variables with a "LOOKUP" slot were introduced as non-locals 1294 // Variables with a "LOOKUP" slot were introduced as non-locals
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1698 target.SetValue(NOT_CONST_INIT); 1335 target.SetValue(NOT_CONST_INIT);
1699 // Get rid of the assigned value (declarations are statements). It's 1336 // Get rid of the assigned value (declarations are statements). It's
1700 // safe to pop the value lying on top of the reference before unloading 1337 // safe to pop the value lying on top of the reference before unloading
1701 // the reference itself (which preserves the top of stack) because we 1338 // the reference itself (which preserves the top of stack) because we
1702 // know that it is a zero-sized reference. 1339 // know that it is a zero-sized reference.
1703 __ pop(eax); // Pop(no_reg); 1340 __ pop(eax); // Pop(no_reg);
1704 } 1341 }
1705 } 1342 }
1706 1343
1707 1344
1708 void Ia32CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { 1345 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
1709 Comment cmnt(masm_, "[ ExpressionStatement"); 1346 Comment cmnt(masm_, "[ ExpressionStatement");
1710 RecordStatementPosition(node); 1347 RecordStatementPosition(node);
1711 Expression* expression = node->expression(); 1348 Expression* expression = node->expression();
1712 expression->MarkAsStatement(); 1349 expression->MarkAsStatement();
1713 Load(expression); 1350 Load(expression);
1714 __ pop(eax); // remove the lingering expression result from the top of stack 1351 __ pop(eax); // remove the lingering expression result from the top of stack
1715 } 1352 }
1716 1353
1717 1354
1718 void Ia32CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { 1355 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
1719 Comment cmnt(masm_, "// EmptyStatement"); 1356 Comment cmnt(masm_, "// EmptyStatement");
1720 // nothing to do 1357 // nothing to do
1721 } 1358 }
1722 1359
1723 1360
1724 void Ia32CodeGenerator::VisitIfStatement(IfStatement* node) { 1361 void CodeGenerator::VisitIfStatement(IfStatement* node) {
1725 Comment cmnt(masm_, "[ IfStatement"); 1362 Comment cmnt(masm_, "[ IfStatement");
1726 // Generate different code depending on which 1363 // Generate different code depending on which
1727 // parts of the if statement are present or not. 1364 // parts of the if statement are present or not.
1728 bool has_then_stm = node->HasThenStatement(); 1365 bool has_then_stm = node->HasThenStatement();
1729 bool has_else_stm = node->HasElseStatement(); 1366 bool has_else_stm = node->HasElseStatement();
1730 1367
1731 RecordStatementPosition(node); 1368 RecordStatementPosition(node);
1732 Label exit; 1369 Label exit;
1733 if (has_then_stm && has_else_stm) { 1370 if (has_then_stm && has_else_stm) {
1734 Label then; 1371 Label then;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1775 // Pop it again, since it is not going to be used. 1412 // Pop it again, since it is not going to be used.
1776 __ pop(eax); 1413 __ pop(eax);
1777 } 1414 }
1778 } 1415 }
1779 1416
1780 // end 1417 // end
1781 __ bind(&exit); 1418 __ bind(&exit);
1782 } 1419 }
1783 1420
1784 1421
1785 void Ia32CodeGenerator::CleanStack(int num_bytes) { 1422 void CodeGenerator::CleanStack(int num_bytes) {
1786 ASSERT(num_bytes >= 0); 1423 ASSERT(num_bytes >= 0);
1787 if (num_bytes > 0) { 1424 if (num_bytes > 0) {
1788 __ add(Operand(esp), Immediate(num_bytes)); 1425 __ add(Operand(esp), Immediate(num_bytes));
1789 } 1426 }
1790 } 1427 }
1791 1428
1792 1429
1793 void Ia32CodeGenerator::VisitContinueStatement(ContinueStatement* node) { 1430 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
1794 Comment cmnt(masm_, "[ ContinueStatement"); 1431 Comment cmnt(masm_, "[ ContinueStatement");
1795 RecordStatementPosition(node); 1432 RecordStatementPosition(node);
1796 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1433 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1797 __ jmp(node->target()->continue_target()); 1434 __ jmp(node->target()->continue_target());
1798 } 1435 }
1799 1436
1800 1437
1801 void Ia32CodeGenerator::VisitBreakStatement(BreakStatement* node) { 1438 void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
1802 Comment cmnt(masm_, "[ BreakStatement"); 1439 Comment cmnt(masm_, "[ BreakStatement");
1803 RecordStatementPosition(node); 1440 RecordStatementPosition(node);
1804 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1441 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1805 __ jmp(node->target()->break_target()); 1442 __ jmp(node->target()->break_target());
1806 } 1443 }
1807 1444
1808 1445
1809 void Ia32CodeGenerator::VisitReturnStatement(ReturnStatement* node) { 1446 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
1810 Comment cmnt(masm_, "[ ReturnStatement"); 1447 Comment cmnt(masm_, "[ ReturnStatement");
1811 RecordStatementPosition(node); 1448 RecordStatementPosition(node);
1812 Load(node->expression()); 1449 Load(node->expression());
1813 1450
1814 // Move the function result into eax 1451 // Move the function result into eax
1815 __ pop(eax); 1452 __ pop(eax);
1816 1453
1817 // If we're inside a try statement or the return instruction 1454 // If we're inside a try statement or the return instruction
1818 // sequence has been generated, we just jump to that 1455 // sequence has been generated, we just jump to that
1819 // point. Otherwise, we generate the return instruction sequence and 1456 // point. Otherwise, we generate the return instruction sequence and
(...skipping 17 matching lines...) Expand all
1837 __ ret((scope_->num_parameters() + 1) * kPointerSize); 1474 __ ret((scope_->num_parameters() + 1) * kPointerSize);
1838 1475
1839 // Check that the size of the code used for returning matches what is 1476 // Check that the size of the code used for returning matches what is
1840 // expected by the debugger. 1477 // expected by the debugger.
1841 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, 1478 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
1842 __ SizeOfCodeGeneratedSince(&check_exit_codesize)); 1479 __ SizeOfCodeGeneratedSince(&check_exit_codesize));
1843 } 1480 }
1844 } 1481 }
1845 1482
1846 1483
1847 void Ia32CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 1484 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
1848 Comment cmnt(masm_, "[ WithEnterStatement"); 1485 Comment cmnt(masm_, "[ WithEnterStatement");
1849 RecordStatementPosition(node); 1486 RecordStatementPosition(node);
1850 Load(node->expression()); 1487 Load(node->expression());
1851 __ CallRuntime(Runtime::kPushContext, 1); 1488 __ CallRuntime(Runtime::kPushContext, 1);
1852 1489
1853 if (kDebug) { 1490 if (kDebug) {
1854 Label verified_true; 1491 Label verified_true;
1855 // Verify eax and esi are the same in debug mode 1492 // Verify eax and esi are the same in debug mode
1856 __ cmp(eax, Operand(esi)); 1493 __ cmp(eax, Operand(esi));
1857 __ j(equal, &verified_true); 1494 __ j(equal, &verified_true);
1858 __ int3(); 1495 __ int3();
1859 __ bind(&verified_true); 1496 __ bind(&verified_true);
1860 } 1497 }
1861 1498
1862 // Update context local. 1499 // Update context local.
1863 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 1500 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
1864 } 1501 }
1865 1502
1866 1503
1867 void Ia32CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { 1504 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
1868 Comment cmnt(masm_, "[ WithExitStatement"); 1505 Comment cmnt(masm_, "[ WithExitStatement");
1869 // Pop context. 1506 // Pop context.
1870 __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX)); 1507 __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX));
1871 // Update context local. 1508 // Update context local.
1872 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 1509 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
1873 } 1510 }
1874 1511
1875 int Ia32CodeGenerator::FastCaseSwitchMaxOverheadFactor() { 1512 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() {
1876 return kFastSwitchMaxOverheadFactor; 1513 return kFastSwitchMaxOverheadFactor;
1877 } 1514 }
1878 1515
1879 int Ia32CodeGenerator::FastCaseSwitchMinCaseCount() { 1516 int CodeGenerator::FastCaseSwitchMinCaseCount() {
1880 return kFastSwitchMinCaseCount; 1517 return kFastSwitchMinCaseCount;
1881 } 1518 }
1882 1519
1883 // Generate a computed jump to a switch case. 1520 // Generate a computed jump to a switch case.
1884 void Ia32CodeGenerator::GenerateFastCaseSwitchJumpTable( 1521 void CodeGenerator::GenerateFastCaseSwitchJumpTable(
1885 SwitchStatement* node, int min_index, int range, Label *fail_label, 1522 SwitchStatement* node, int min_index, int range, Label *fail_label,
1886 SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels) { 1523 SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels) {
1887 // Notice: Internal references, used by both the jmp instruction and 1524 // Notice: Internal references, used by both the jmp instruction and
1888 // the table entries, need to be relocated if the buffer grows. This 1525 // the table entries, need to be relocated if the buffer grows. This
1889 // prevents the forward use of Labels, since a displacement cannot 1526 // prevents the forward use of Labels, since a displacement cannot
1890 // survive relocation, and it also cannot safely be distinguished 1527 // survive relocation, and it also cannot safely be distinguished
1891 // from a real address. Instead we put in zero-values as 1528 // from a real address. Instead we put in zero-values as
1892 // placeholders, and fill in the addresses after the labels have been 1529 // placeholders, and fill in the addresses after the labels have been
1893 // bound. 1530 // bound.
1894 1531
(...skipping 25 matching lines...) Expand all
1920 1557
1921 GenerateFastCaseSwitchCases(node, case_labels); 1558 GenerateFastCaseSwitchCases(node, case_labels);
1922 1559
1923 for (int i = 0, entry_pos = table_start.pos(); 1560 for (int i = 0, entry_pos = table_start.pos();
1924 i < range; i++, entry_pos += sizeof(uint32_t)) { 1561 i < range; i++, entry_pos += sizeof(uint32_t)) {
1925 __ WriteInternalReference(entry_pos, *case_targets[i]); 1562 __ WriteInternalReference(entry_pos, *case_targets[i]);
1926 } 1563 }
1927 } 1564 }
1928 1565
1929 1566
1930 void Ia32CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { 1567 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
1931 Comment cmnt(masm_, "[ SwitchStatement"); 1568 Comment cmnt(masm_, "[ SwitchStatement");
1932 RecordStatementPosition(node); 1569 RecordStatementPosition(node);
1933 node->set_break_stack_height(break_stack_height_); 1570 node->set_break_stack_height(break_stack_height_);
1934 1571
1935 Load(node->tag()); 1572 Load(node->tag());
1936 1573
1937 if (TryGenerateFastCaseSwitchStatement(node)) { 1574 if (TryGenerateFastCaseSwitchStatement(node)) {
1938 return; 1575 return;
1939 } 1576 }
1940 1577
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1987 } else { 1624 } else {
1988 // Remove the switch value from the stack. 1625 // Remove the switch value from the stack.
1989 __ pop(eax); 1626 __ pop(eax);
1990 } 1627 }
1991 1628
1992 __ bind(&fall_through); 1629 __ bind(&fall_through);
1993 __ bind(node->break_target()); 1630 __ bind(node->break_target());
1994 } 1631 }
1995 1632
1996 1633
1997 void Ia32CodeGenerator::VisitLoopStatement(LoopStatement* node) { 1634 void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
1998 Comment cmnt(masm_, "[ LoopStatement"); 1635 Comment cmnt(masm_, "[ LoopStatement");
1999 RecordStatementPosition(node); 1636 RecordStatementPosition(node);
2000 node->set_break_stack_height(break_stack_height_); 1637 node->set_break_stack_height(break_stack_height_);
2001 1638
2002 // simple condition analysis 1639 // simple condition analysis
2003 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; 1640 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW;
2004 if (node->cond() == NULL) { 1641 if (node->cond() == NULL) {
2005 ASSERT(node->type() == LoopStatement::FOR_LOOP); 1642 ASSERT(node->type() == LoopStatement::FOR_LOOP);
2006 info = ALWAYS_TRUE; 1643 info = ALWAYS_TRUE;
2007 } else { 1644 } else {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2056 node->break_target(), true); 1693 node->break_target(), true);
2057 Branch(true, &loop); 1694 Branch(true, &loop);
2058 break; 1695 break;
2059 } 1696 }
2060 1697
2061 // exit 1698 // exit
2062 __ bind(node->break_target()); 1699 __ bind(node->break_target());
2063 } 1700 }
2064 1701
2065 1702
2066 void Ia32CodeGenerator::VisitForInStatement(ForInStatement* node) { 1703 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
2067 Comment cmnt(masm_, "[ ForInStatement"); 1704 Comment cmnt(masm_, "[ ForInStatement");
2068 RecordStatementPosition(node); 1705 RecordStatementPosition(node);
2069 1706
2070 // We keep stuff on the stack while the body is executing. 1707 // We keep stuff on the stack while the body is executing.
2071 // Record it, so that a break/continue crossing this statement 1708 // Record it, so that a break/continue crossing this statement
2072 // can restore the stack. 1709 // can restore the stack.
2073 const int kForInStackSize = 5 * kPointerSize; 1710 const int kForInStackSize = 5 * kPointerSize;
2074 break_stack_height_ += kForInStackSize; 1711 break_stack_height_ += kForInStackSize;
2075 node->set_break_stack_height(break_stack_height_); 1712 node->set_break_stack_height(break_stack_height_);
2076 1713
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
2244 __ bind(node->break_target()); 1881 __ bind(node->break_target());
2245 __ add(Operand(esp), Immediate(5 * kPointerSize)); 1882 __ add(Operand(esp), Immediate(5 * kPointerSize));
2246 1883
2247 // Exit. 1884 // Exit.
2248 __ bind(&exit); 1885 __ bind(&exit);
2249 1886
2250 break_stack_height_ -= kForInStackSize; 1887 break_stack_height_ -= kForInStackSize;
2251 } 1888 }
2252 1889
2253 1890
2254 void Ia32CodeGenerator::VisitTryCatch(TryCatch* node) { 1891 void CodeGenerator::VisitTryCatch(TryCatch* node) {
2255 Comment cmnt(masm_, "[ TryCatch"); 1892 Comment cmnt(masm_, "[ TryCatch");
2256 1893
2257 Label try_block, exit; 1894 Label try_block, exit;
2258 1895
2259 __ call(&try_block); 1896 __ call(&try_block);
2260 // --- Catch block --- 1897 // --- Catch block ---
2261 __ push(eax); 1898 __ push(eax);
2262 1899
2263 // Store the caught exception in the catch variable. 1900 // Store the caught exception in the catch variable.
2264 { Reference ref(this, node->catch_var()); 1901 { Reference ref(this, node->catch_var());
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2343 Immediate(StackHandlerConstants::kSize - kPointerSize)); 1980 Immediate(StackHandlerConstants::kSize - kPointerSize));
2344 // next_sp popped. 1981 // next_sp popped.
2345 __ jmp(shadows[i]->shadowed()); 1982 __ jmp(shadows[i]->shadowed());
2346 } 1983 }
2347 } 1984 }
2348 1985
2349 __ bind(&exit); 1986 __ bind(&exit);
2350 } 1987 }
2351 1988
2352 1989
2353 void Ia32CodeGenerator::VisitTryFinally(TryFinally* node) { 1990 void CodeGenerator::VisitTryFinally(TryFinally* node) {
2354 Comment cmnt(masm_, "[ TryFinally"); 1991 Comment cmnt(masm_, "[ TryFinally");
2355 1992
2356 // State: Used to keep track of reason for entering the finally 1993 // State: Used to keep track of reason for entering the finally
2357 // block. Should probably be extended to hold information for 1994 // block. Should probably be extended to hold information for
2358 // break/continue from within the try block. 1995 // break/continue from within the try block.
2359 enum { FALLING, THROWING, JUMPING }; 1996 enum { FALLING, THROWING, JUMPING };
2360 1997
2361 Label exit, unlink, try_block, finally_block; 1998 Label exit, unlink, try_block, finally_block;
2362 1999
2363 __ call(&try_block); 2000 __ call(&try_block);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
2472 2109
2473 // Rethrow exception. 2110 // Rethrow exception.
2474 __ push(eax); // undo pop from above 2111 __ push(eax); // undo pop from above
2475 __ CallRuntime(Runtime::kReThrow, 1); 2112 __ CallRuntime(Runtime::kReThrow, 1);
2476 2113
2477 // Done. 2114 // Done.
2478 __ bind(&exit); 2115 __ bind(&exit);
2479 } 2116 }
2480 2117
2481 2118
2482 void Ia32CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { 2119 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
2483 Comment cmnt(masm_, "[ DebuggerStatement"); 2120 Comment cmnt(masm_, "[ DebuggerStatement");
2484 RecordStatementPosition(node); 2121 RecordStatementPosition(node);
2485 __ CallRuntime(Runtime::kDebugBreak, 1); 2122 __ CallRuntime(Runtime::kDebugBreak, 1);
2486 __ push(eax); 2123 __ push(eax);
2487 } 2124 }
2488 2125
2489 2126
2490 void Ia32CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { 2127 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
2491 ASSERT(boilerplate->IsBoilerplate()); 2128 ASSERT(boilerplate->IsBoilerplate());
2492 2129
2493 // Push the boilerplate on the stack. 2130 // Push the boilerplate on the stack.
2494 __ push(Immediate(boilerplate)); 2131 __ push(Immediate(boilerplate));
2495 2132
2496 // Create a new closure. 2133 // Create a new closure.
2497 __ push(esi); 2134 __ push(esi);
2498 __ CallRuntime(Runtime::kNewClosure, 2); 2135 __ CallRuntime(Runtime::kNewClosure, 2);
2499 __ push(eax); 2136 __ push(eax);
2500 } 2137 }
2501 2138
2502 2139
2503 void Ia32CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 2140 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
2504 Comment cmnt(masm_, "[ FunctionLiteral"); 2141 Comment cmnt(masm_, "[ FunctionLiteral");
2505 2142
2506 // Build the function boilerplate and instantiate it. 2143 // Build the function boilerplate and instantiate it.
2507 Handle<JSFunction> boilerplate = BuildBoilerplate(node); 2144 Handle<JSFunction> boilerplate = BuildBoilerplate(node);
2508 // Check for stack-overflow exception. 2145 // Check for stack-overflow exception.
2509 if (HasStackOverflow()) return; 2146 if (HasStackOverflow()) return;
2510 InstantiateBoilerplate(boilerplate); 2147 InstantiateBoilerplate(boilerplate);
2511 } 2148 }
2512 2149
2513 2150
2514 void Ia32CodeGenerator::VisitFunctionBoilerplateLiteral( 2151 void CodeGenerator::VisitFunctionBoilerplateLiteral(
2515 FunctionBoilerplateLiteral* node) { 2152 FunctionBoilerplateLiteral* node) {
2516 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 2153 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
2517 InstantiateBoilerplate(node->boilerplate()); 2154 InstantiateBoilerplate(node->boilerplate());
2518 } 2155 }
2519 2156
2520 2157
2521 void Ia32CodeGenerator::VisitConditional(Conditional* node) { 2158 void CodeGenerator::VisitConditional(Conditional* node) {
2522 Comment cmnt(masm_, "[ Conditional"); 2159 Comment cmnt(masm_, "[ Conditional");
2523 Label then, else_, exit; 2160 Label then, else_, exit;
2524 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); 2161 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
2525 Branch(false, &else_); 2162 Branch(false, &else_);
2526 __ bind(&then); 2163 __ bind(&then);
2527 Load(node->then_expression(), typeof_state()); 2164 Load(node->then_expression(), typeof_state());
2528 __ jmp(&exit); 2165 __ jmp(&exit);
2529 __ bind(&else_); 2166 __ bind(&else_);
2530 Load(node->else_expression(), typeof_state()); 2167 Load(node->else_expression(), typeof_state());
2531 __ bind(&exit); 2168 __ bind(&exit);
2532 } 2169 }
2533 2170
2534 2171
2535 void Ia32CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2172 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2536 if (slot->type() == Slot::LOOKUP) { 2173 if (slot->type() == Slot::LOOKUP) {
2537 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2174 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2538 2175
2539 // For now, just do a runtime call. 2176 // For now, just do a runtime call.
2540 __ push(esi); 2177 __ push(esi);
2541 __ push(Immediate(slot->var()->name())); 2178 __ push(Immediate(slot->var()->name()));
2542 2179
2543 if (typeof_state == INSIDE_TYPEOF) { 2180 if (typeof_state == INSIDE_TYPEOF) {
2544 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2181 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2545 } else { 2182 } else {
(...skipping 17 matching lines...) Expand all
2563 __ mov(eax, Factory::undefined_value()); 2200 __ mov(eax, Factory::undefined_value());
2564 __ bind(&exit); 2201 __ bind(&exit);
2565 __ push(eax); 2202 __ push(eax);
2566 } else { 2203 } else {
2567 __ push(SlotOperand(slot, ecx)); 2204 __ push(SlotOperand(slot, ecx));
2568 } 2205 }
2569 } 2206 }
2570 } 2207 }
2571 2208
2572 2209
2573 void Ia32CodeGenerator::VisitSlot(Slot* node) { 2210 void CodeGenerator::VisitSlot(Slot* node) {
2574 Comment cmnt(masm_, "[ Slot"); 2211 Comment cmnt(masm_, "[ Slot");
2575 LoadFromSlot(node, typeof_state()); 2212 LoadFromSlot(node, typeof_state());
2576 } 2213 }
2577 2214
2578 2215
2579 void Ia32CodeGenerator::VisitVariableProxy(VariableProxy* node) { 2216 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
2580 Comment cmnt(masm_, "[ VariableProxy"); 2217 Comment cmnt(masm_, "[ VariableProxy");
2581 Variable* var = node->var(); 2218 Variable* var = node->var();
2582 Expression* expr = var->rewrite(); 2219 Expression* expr = var->rewrite();
2583 if (expr != NULL) { 2220 if (expr != NULL) {
2584 Visit(expr); 2221 Visit(expr);
2585 } else { 2222 } else {
2586 ASSERT(var->is_global()); 2223 ASSERT(var->is_global());
2587 Reference ref(this, node); 2224 Reference ref(this, node);
2588 ref.GetValue(typeof_state()); 2225 ref.GetValue(typeof_state());
2589 } 2226 }
2590 } 2227 }
2591 2228
2592 2229
2593 void Ia32CodeGenerator::VisitLiteral(Literal* node) { 2230 void CodeGenerator::VisitLiteral(Literal* node) {
2594 Comment cmnt(masm_, "[ Literal"); 2231 Comment cmnt(masm_, "[ Literal");
2595 if (node->handle()->IsSmi() && !IsInlineSmi(node)) { 2232 if (node->handle()->IsSmi() && !IsInlineSmi(node)) {
2596 // To prevent long attacker-controlled byte sequences in code, larger 2233 // To prevent long attacker-controlled byte sequences in code, larger
2597 // Smis are loaded in two steps. 2234 // Smis are loaded in two steps.
2598 int bits = reinterpret_cast<int>(*node->handle()); 2235 int bits = reinterpret_cast<int>(*node->handle());
2599 __ mov(eax, bits & 0x0000FFFF); 2236 __ mov(eax, bits & 0x0000FFFF);
2600 __ xor_(eax, bits & 0xFFFF0000); 2237 __ xor_(eax, bits & 0xFFFF0000);
2601 __ push(eax); 2238 __ push(eax);
2602 } else { 2239 } else {
2603 __ push(Immediate(node->handle())); 2240 __ push(Immediate(node->handle()));
(...skipping 23 matching lines...) Expand all
2627 __ push(Immediate(Smi::FromInt(node_->literal_index()))); 2264 __ push(Immediate(Smi::FromInt(node_->literal_index())));
2628 // RegExp pattern (2). 2265 // RegExp pattern (2).
2629 __ push(Immediate(node_->pattern())); 2266 __ push(Immediate(node_->pattern()));
2630 // RegExp flags (3). 2267 // RegExp flags (3).
2631 __ push(Immediate(node_->flags())); 2268 __ push(Immediate(node_->flags()));
2632 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 2269 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
2633 __ mov(ebx, Operand(eax)); // "caller" expects result in ebx 2270 __ mov(ebx, Operand(eax)); // "caller" expects result in ebx
2634 } 2271 }
2635 2272
2636 2273
2637 void Ia32CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 2274 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
2638 Comment cmnt(masm_, "[ RegExp Literal"); 2275 Comment cmnt(masm_, "[ RegExp Literal");
2639 RegExpDeferred* deferred = new RegExpDeferred(this, node); 2276 RegExpDeferred* deferred = new RegExpDeferred(this, node);
2640 2277
2641 // Retrieve the literal array and check the allocated entry. 2278 // Retrieve the literal array and check the allocated entry.
2642 2279
2643 // Load the function of this activation. 2280 // Load the function of this activation.
2644 __ mov(ecx, FunctionOperand()); 2281 __ mov(ecx, FunctionOperand());
2645 2282
2646 // Load the literals array of the function. 2283 // Load the literals array of the function.
2647 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2284 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2687 __ push(Operand(ecx)); 2324 __ push(Operand(ecx));
2688 // Literal index (1). 2325 // Literal index (1).
2689 __ push(Immediate(Smi::FromInt(node_->literal_index()))); 2326 __ push(Immediate(Smi::FromInt(node_->literal_index())));
2690 // Constant properties (2). 2327 // Constant properties (2).
2691 __ push(Immediate(node_->constant_properties())); 2328 __ push(Immediate(node_->constant_properties()));
2692 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); 2329 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
2693 __ mov(ebx, Operand(eax)); 2330 __ mov(ebx, Operand(eax));
2694 } 2331 }
2695 2332
2696 2333
2697 void Ia32CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 2334 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
2698 Comment cmnt(masm_, "[ ObjectLiteral"); 2335 Comment cmnt(masm_, "[ ObjectLiteral");
2699 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); 2336 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);
2700 2337
2701 // Retrieve the literal array and check the allocated entry. 2338 // Retrieve the literal array and check the allocated entry.
2702 2339
2703 // Load the function of this activation. 2340 // Load the function of this activation.
2704 __ mov(ecx, FunctionOperand()); 2341 __ mov(ecx, FunctionOperand());
2705 2342
2706 // Load the literals array of the function. 2343 // Load the literals array of the function.
2707 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2344 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
2777 __ CallRuntime(Runtime::kDefineAccessor, 4); 2414 __ CallRuntime(Runtime::kDefineAccessor, 4);
2778 // Ignore result. 2415 // Ignore result.
2779 break; 2416 break;
2780 } 2417 }
2781 default: UNREACHABLE(); 2418 default: UNREACHABLE();
2782 } 2419 }
2783 } 2420 }
2784 } 2421 }
2785 2422
2786 2423
2787 void Ia32CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 2424 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
2788 Comment cmnt(masm_, "[ ArrayLiteral"); 2425 Comment cmnt(masm_, "[ ArrayLiteral");
2789 2426
2790 // Call runtime to create the array literal. 2427 // Call runtime to create the array literal.
2791 __ push(Immediate(node->literals())); 2428 __ push(Immediate(node->literals()));
2792 // Load the function of this frame. 2429 // Load the function of this frame.
2793 __ mov(ecx, FunctionOperand()); 2430 __ mov(ecx, FunctionOperand());
2794 // Load the literals array of the function. 2431 // Load the literals array of the function.
2795 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2432 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
2796 __ push(ecx); 2433 __ push(ecx);
2797 __ CallRuntime(Runtime::kCreateArrayLiteral, 2); 2434 __ CallRuntime(Runtime::kCreateArrayLiteral, 2);
(...skipping 23 matching lines...) Expand all
2821 int offset = i * kPointerSize + Array::kHeaderSize; 2458 int offset = i * kPointerSize + Array::kHeaderSize;
2822 __ mov(FieldOperand(ecx, offset), eax); 2459 __ mov(FieldOperand(ecx, offset), eax);
2823 2460
2824 // Update the write barrier for the array address. 2461 // Update the write barrier for the array address.
2825 __ RecordWrite(ecx, offset, eax, ebx); 2462 __ RecordWrite(ecx, offset, eax, ebx);
2826 } 2463 }
2827 } 2464 }
2828 } 2465 }
2829 2466
2830 2467
2831 bool Ia32CodeGenerator::IsInlineSmi(Literal* literal) { 2468 bool CodeGenerator::IsInlineSmi(Literal* literal) {
2832 if (literal == NULL || !literal->handle()->IsSmi()) return false; 2469 if (literal == NULL || !literal->handle()->IsSmi()) return false;
2833 int int_value = Smi::cast(*literal->handle())->value(); 2470 int int_value = Smi::cast(*literal->handle())->value();
2834 return is_intn(int_value, kMaxSmiInlinedBits); 2471 return is_intn(int_value, kMaxSmiInlinedBits);
2835 } 2472 }
2836 2473
2837 2474
2838 void Ia32CodeGenerator::VisitAssignment(Assignment* node) { 2475 void CodeGenerator::VisitAssignment(Assignment* node) {
2839 Comment cmnt(masm_, "[ Assignment"); 2476 Comment cmnt(masm_, "[ Assignment");
2840 2477
2841 RecordStatementPosition(node); 2478 RecordStatementPosition(node);
2842 Reference target(this, node->target()); 2479 Reference target(this, node->target());
2843 if (target.is_illegal()) return; 2480 if (target.is_illegal()) return;
2844 2481
2845 if (node->op() == Token::ASSIGN || 2482 if (node->op() == Token::ASSIGN ||
2846 node->op() == Token::INIT_VAR || 2483 node->op() == Token::INIT_VAR ||
2847 node->op() == Token::INIT_CONST) { 2484 node->op() == Token::INIT_CONST) {
2848 Load(node->value()); 2485 Load(node->value());
(...skipping 21 matching lines...) Expand all
2870 // and initialize the actual constant declared. Dynamic variable 2507 // and initialize the actual constant declared. Dynamic variable
2871 // initializations are simply assignments and use SetValue. 2508 // initializations are simply assignments and use SetValue.
2872 target.SetValue(CONST_INIT); 2509 target.SetValue(CONST_INIT);
2873 } else { 2510 } else {
2874 target.SetValue(NOT_CONST_INIT); 2511 target.SetValue(NOT_CONST_INIT);
2875 } 2512 }
2876 } 2513 }
2877 } 2514 }
2878 2515
2879 2516
2880 void Ia32CodeGenerator::VisitThrow(Throw* node) { 2517 void CodeGenerator::VisitThrow(Throw* node) {
2881 Comment cmnt(masm_, "[ Throw"); 2518 Comment cmnt(masm_, "[ Throw");
2882 2519
2883 Load(node->exception()); 2520 Load(node->exception());
2884 __ RecordPosition(node->position()); 2521 __ RecordPosition(node->position());
2885 __ CallRuntime(Runtime::kThrow, 1); 2522 __ CallRuntime(Runtime::kThrow, 1);
2886 __ push(eax); 2523 __ push(eax);
2887 } 2524 }
2888 2525
2889 2526
2890 void Ia32CodeGenerator::VisitProperty(Property* node) { 2527 void CodeGenerator::VisitProperty(Property* node) {
2891 Comment cmnt(masm_, "[ Property"); 2528 Comment cmnt(masm_, "[ Property");
2529
2892 Reference property(this, node); 2530 Reference property(this, node);
2893 property.GetValue(typeof_state()); 2531 property.GetValue(typeof_state());
2894 } 2532 }
2895 2533
2896 2534
2897 void Ia32CodeGenerator::VisitCall(Call* node) { 2535 void CodeGenerator::VisitCall(Call* node) {
2898 Comment cmnt(masm_, "[ Call"); 2536 Comment cmnt(masm_, "[ Call");
2899 2537
2900 ZoneList<Expression*>* args = node->arguments(); 2538 ZoneList<Expression*>* args = node->arguments();
2901 2539
2902 RecordStatementPosition(node); 2540 RecordStatementPosition(node);
2903 2541
2904 // Check if the function is a variable or a property. 2542 // Check if the function is a variable or a property.
2905 Expression* function = node->expression(); 2543 Expression* function = node->expression();
2906 Variable* var = function->AsVariableProxy()->AsVariable(); 2544 Variable* var = function->AsVariableProxy()->AsVariable();
2907 Property* property = function->AsProperty(); 2545 Property* property = function->AsProperty();
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
3009 2647
3010 // Pass the global object as the receiver. 2648 // Pass the global object as the receiver.
3011 LoadGlobal(); 2649 LoadGlobal();
3012 2650
3013 // Call the function. 2651 // Call the function.
3014 CallWithArguments(args, node->position()); 2652 CallWithArguments(args, node->position());
3015 } 2653 }
3016 } 2654 }
3017 2655
3018 2656
3019 void Ia32CodeGenerator::VisitCallNew(CallNew* node) { 2657 void CodeGenerator::VisitCallNew(CallNew* node) {
3020 Comment cmnt(masm_, "[ CallNew"); 2658 Comment cmnt(masm_, "[ CallNew");
3021 2659
3022 // According to ECMA-262, section 11.2.2, page 44, the function 2660 // According to ECMA-262, section 11.2.2, page 44, the function
3023 // expression in new calls must be evaluated before the 2661 // expression in new calls must be evaluated before the
3024 // arguments. This is different from ordinary calls, where the 2662 // arguments. This is different from ordinary calls, where the
3025 // actual function to call is resolved after the arguments have been 2663 // actual function to call is resolved after the arguments have been
3026 // evaluated. 2664 // evaluated.
3027 2665
3028 // Compute function to call and use the global object as the 2666 // Compute function to call and use the global object as the
3029 // receiver. 2667 // receiver.
(...skipping 15 matching lines...) Expand all
3045 2683
3046 // Call the construct call builtin that handles allocation and 2684 // Call the construct call builtin that handles allocation and
3047 // constructor invocation. 2685 // constructor invocation.
3048 __ RecordPosition(node->position()); 2686 __ RecordPosition(node->position());
3049 __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), 2687 __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
3050 RelocInfo::CONSTRUCT_CALL); 2688 RelocInfo::CONSTRUCT_CALL);
3051 __ mov(TOS, eax); // discard the function and "push" the newly created object 2689 __ mov(TOS, eax); // discard the function and "push" the newly created object
3052 } 2690 }
3053 2691
3054 2692
3055 void Ia32CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 2693 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
3056 ASSERT(args->length() == 1); 2694 ASSERT(args->length() == 1);
3057 Load(args->at(0)); 2695 Load(args->at(0));
3058 __ pop(eax); 2696 __ pop(eax);
3059 __ test(eax, Immediate(kSmiTagMask)); 2697 __ test(eax, Immediate(kSmiTagMask));
3060 cc_reg_ = zero; 2698 cc_reg_ = zero;
3061 } 2699 }
3062 2700
3063 2701
3064 void Ia32CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 2702 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
3065 ASSERT(args->length() == 1); 2703 ASSERT(args->length() == 1);
3066 Load(args->at(0)); 2704 Load(args->at(0));
3067 __ pop(eax); 2705 __ pop(eax);
3068 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 2706 __ test(eax, Immediate(kSmiTagMask | 0x80000000));
3069 cc_reg_ = zero; 2707 cc_reg_ = zero;
3070 } 2708 }
3071 2709
3072 2710
3073 // This generates code that performs a charCodeAt() call or returns 2711 // This generates code that performs a charCodeAt() call or returns
3074 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 2712 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
3075 // It can handle flat and sliced strings, 8 and 16 bit characters and 2713 // It can handle flat and sliced strings, 8 and 16 bit characters and
3076 // cons strings where the answer is found in the left hand branch of the 2714 // cons strings where the answer is found in the left hand branch of the
3077 // cons. The slow case will flatten the string, which will ensure that 2715 // cons. The slow case will flatten the string, which will ensure that
3078 // the answer is in the left hand side the next time around. 2716 // the answer is in the left hand side the next time around.
3079 void Ia32CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 2717 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
3080 ASSERT(args->length() == 2); 2718 ASSERT(args->length() == 2);
3081 2719
3082 Label slow_case; 2720 Label slow_case;
3083 Label end; 2721 Label end;
3084 Label not_a_flat_string; 2722 Label not_a_flat_string;
3085 Label not_a_cons_string_either; 2723 Label not_a_cons_string_either;
3086 Label try_again_with_new_string; 2724 Label try_again_with_new_string;
3087 Label ascii_string; 2725 Label ascii_string;
3088 Label got_char_code; 2726 Label got_char_code;
3089 2727
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
3195 __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset)); 2833 __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset));
3196 __ jmp(&try_again_with_new_string); 2834 __ jmp(&try_again_with_new_string);
3197 2835
3198 __ bind(&slow_case); 2836 __ bind(&slow_case);
3199 __ push(Immediate(Factory::undefined_value())); 2837 __ push(Immediate(Factory::undefined_value()));
3200 2838
3201 __ bind(&end); 2839 __ bind(&end);
3202 } 2840 }
3203 2841
3204 2842
3205 void Ia32CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 2843 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
3206 ASSERT(args->length() == 1); 2844 ASSERT(args->length() == 1);
3207 Load(args->at(0)); 2845 Load(args->at(0));
3208 Label answer; 2846 Label answer;
3209 // We need the CC bits to come out as not_equal in the case where the 2847 // We need the CC bits to come out as not_equal in the case where the
3210 // object is a smi. This can't be done with the usual test opcode so 2848 // object is a smi. This can't be done with the usual test opcode so
3211 // we copy the object to ecx and do some destructive ops on it that 2849 // we copy the object to ecx and do some destructive ops on it that
3212 // result in the right CC bits. 2850 // result in the right CC bits.
3213 __ pop(eax); 2851 __ pop(eax);
3214 __ mov(ecx, Operand(eax)); 2852 __ mov(ecx, Operand(eax));
3215 __ and_(ecx, kSmiTagMask); 2853 __ and_(ecx, kSmiTagMask);
3216 __ xor_(ecx, kSmiTagMask); 2854 __ xor_(ecx, kSmiTagMask);
3217 __ j(not_equal, &answer, not_taken); 2855 __ j(not_equal, &answer, not_taken);
3218 // It is a heap object - get map. 2856 // It is a heap object - get map.
3219 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 2857 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
3220 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); 2858 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
3221 // Check if the object is a JS array or not. 2859 // Check if the object is a JS array or not.
3222 __ cmp(eax, JS_ARRAY_TYPE); 2860 __ cmp(eax, JS_ARRAY_TYPE);
3223 __ bind(&answer); 2861 __ bind(&answer);
3224 cc_reg_ = equal; 2862 cc_reg_ = equal;
3225 } 2863 }
3226 2864
3227 2865
3228 void Ia32CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 2866 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
3229 ASSERT(args->length() == 0); 2867 ASSERT(args->length() == 0);
3230 2868
3231 // Seed the result with the formal parameters count, which will be 2869 // Seed the result with the formal parameters count, which will be
3232 // used in case no arguments adaptor frame is found below the 2870 // used in case no arguments adaptor frame is found below the
3233 // current frame. 2871 // current frame.
3234 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); 2872 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
3235 2873
3236 // Call the shared stub to get to the arguments.length. 2874 // Call the shared stub to get to the arguments.length.
3237 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); 2875 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
3238 __ CallStub(&stub); 2876 __ CallStub(&stub);
3239 __ push(eax); 2877 __ push(eax);
3240 } 2878 }
3241 2879
3242 2880
3243 void Ia32CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 2881 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
3244 ASSERT(args->length() == 1); 2882 ASSERT(args->length() == 1);
3245 Label leave; 2883 Label leave;
3246 Load(args->at(0)); // Load the object. 2884 Load(args->at(0)); // Load the object.
3247 __ mov(eax, TOS); 2885 __ mov(eax, TOS);
3248 // if (object->IsSmi()) return object. 2886 // if (object->IsSmi()) return object.
3249 __ test(eax, Immediate(kSmiTagMask)); 2887 __ test(eax, Immediate(kSmiTagMask));
3250 __ j(zero, &leave, taken); 2888 __ j(zero, &leave, taken);
3251 // It is a heap object - get map. 2889 // It is a heap object - get map.
3252 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 2890 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
3253 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 2891 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
3254 // if (!object->IsJSValue()) return object. 2892 // if (!object->IsJSValue()) return object.
3255 __ cmp(ecx, JS_VALUE_TYPE); 2893 __ cmp(ecx, JS_VALUE_TYPE);
3256 __ j(not_equal, &leave, not_taken); 2894 __ j(not_equal, &leave, not_taken);
3257 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); 2895 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
3258 __ mov(TOS, eax); 2896 __ mov(TOS, eax);
3259 __ bind(&leave); 2897 __ bind(&leave);
3260 } 2898 }
3261 2899
3262 2900
3263 void Ia32CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 2901 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
3264 ASSERT(args->length() == 2); 2902 ASSERT(args->length() == 2);
3265 Label leave; 2903 Label leave;
3266 Load(args->at(0)); // Load the object. 2904 Load(args->at(0)); // Load the object.
3267 Load(args->at(1)); // Load the value. 2905 Load(args->at(1)); // Load the value.
3268 __ mov(eax, (Operand(esp, kPointerSize))); 2906 __ mov(eax, (Operand(esp, kPointerSize)));
3269 __ mov(ecx, TOS); 2907 __ mov(ecx, TOS);
3270 // if (object->IsSmi()) return object. 2908 // if (object->IsSmi()) return object.
3271 __ test(eax, Immediate(kSmiTagMask)); 2909 __ test(eax, Immediate(kSmiTagMask));
3272 __ j(zero, &leave, taken); 2910 __ j(zero, &leave, taken);
3273 // It is a heap object - get map. 2911 // It is a heap object - get map.
3274 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2912 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
3275 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 2913 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
3276 // if (!object->IsJSValue()) return object. 2914 // if (!object->IsJSValue()) return object.
3277 __ cmp(ebx, JS_VALUE_TYPE); 2915 __ cmp(ebx, JS_VALUE_TYPE);
3278 __ j(not_equal, &leave, not_taken); 2916 __ j(not_equal, &leave, not_taken);
3279 // Store the value. 2917 // Store the value.
3280 __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx); 2918 __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx);
3281 // Update the write barrier. 2919 // Update the write barrier.
3282 __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx); 2920 __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx);
3283 // Leave. 2921 // Leave.
3284 __ bind(&leave); 2922 __ bind(&leave);
3285 __ mov(ecx, TOS); 2923 __ mov(ecx, TOS);
3286 __ pop(eax); 2924 __ pop(eax);
3287 __ mov(TOS, ecx); 2925 __ mov(TOS, ecx);
3288 } 2926 }
3289 2927
3290 2928
3291 void Ia32CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 2929 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
3292 ASSERT(args->length() == 1); 2930 ASSERT(args->length() == 1);
3293 2931
3294 // Load the key onto the stack and set register eax to the formal 2932 // Load the key onto the stack and set register eax to the formal
3295 // parameters count for the currently executing function. 2933 // parameters count for the currently executing function.
3296 Load(args->at(0)); 2934 Load(args->at(0));
3297 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); 2935 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
3298 2936
3299 // Call the shared stub to get to arguments[key]. 2937 // Call the shared stub to get to arguments[key].
3300 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2938 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
3301 __ CallStub(&stub); 2939 __ CallStub(&stub);
3302 __ mov(TOS, eax); 2940 __ mov(TOS, eax);
3303 } 2941 }
3304 2942
3305 2943
3306 void Ia32CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 2944 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
3307 ASSERT(args->length() == 2); 2945 ASSERT(args->length() == 2);
3308 2946
3309 // Load the two objects into registers and perform the comparison. 2947 // Load the two objects into registers and perform the comparison.
3310 Load(args->at(0)); 2948 Load(args->at(0));
3311 Load(args->at(1)); 2949 Load(args->at(1));
3312 __ pop(eax); 2950 __ pop(eax);
3313 __ pop(ecx); 2951 __ pop(ecx);
3314 __ cmp(eax, Operand(ecx)); 2952 __ cmp(eax, Operand(ecx));
3315 cc_reg_ = equal; 2953 cc_reg_ = equal;
3316 } 2954 }
3317 2955
3318 2956
3319 void Ia32CodeGenerator::VisitCallRuntime(CallRuntime* node) { 2957 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
3320 if (CheckForInlineRuntimeCall(node)) return; 2958 if (CheckForInlineRuntimeCall(node)) return;
3321 2959
3322 ZoneList<Expression*>* args = node->arguments(); 2960 ZoneList<Expression*>* args = node->arguments();
3323 Comment cmnt(masm_, "[ CallRuntime"); 2961 Comment cmnt(masm_, "[ CallRuntime");
3324 Runtime::Function* function = node->function(); 2962 Runtime::Function* function = node->function();
3325 2963
3326 if (function == NULL) { 2964 if (function == NULL) {
3327 // Prepare stack for calling JS runtime function. 2965 // Prepare stack for calling JS runtime function.
3328 __ push(Immediate(node->name())); 2966 __ push(Immediate(node->name()));
3329 // Push the builtins object found in the current global object. 2967 // Push the builtins object found in the current global object.
(...skipping 13 matching lines...) Expand all
3343 // Call the JS runtime function. 2981 // Call the JS runtime function.
3344 Handle<Code> stub = ComputeCallInitialize(args->length()); 2982 Handle<Code> stub = ComputeCallInitialize(args->length());
3345 __ Set(eax, Immediate(args->length())); 2983 __ Set(eax, Immediate(args->length()));
3346 __ call(stub, RelocInfo::CODE_TARGET); 2984 __ call(stub, RelocInfo::CODE_TARGET);
3347 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2985 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3348 __ mov(TOS, eax); 2986 __ mov(TOS, eax);
3349 } 2987 }
3350 } 2988 }
3351 2989
3352 2990
3353 void Ia32CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 2991 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
3354 Comment cmnt(masm_, "[ UnaryOperation"); 2992 Comment cmnt(masm_, "[ UnaryOperation");
3355 2993
3356 Token::Value op = node->op(); 2994 Token::Value op = node->op();
3357 2995
3358 if (op == Token::NOT) { 2996 if (op == Token::NOT) {
3359 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, 2997 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF,
3360 false_target(), true_target(), true); 2998 false_target(), true_target(), true);
3361 cc_reg_ = NegateCondition(cc_reg_); 2999 cc_reg_ = NegateCondition(cc_reg_);
3362 3000
3363 } else if (op == Token::DELETE) { 3001 } else if (op == Token::DELETE) {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
3552 void CountOperationDeferred::Generate() { 3190 void CountOperationDeferred::Generate() {
3553 if (is_postfix_) { 3191 if (is_postfix_) {
3554 RevertToNumberStub to_number_stub(is_increment_); 3192 RevertToNumberStub to_number_stub(is_increment_);
3555 __ CallStub(&to_number_stub); 3193 __ CallStub(&to_number_stub);
3556 } 3194 }
3557 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); 3195 CounterOpStub stub(result_offset_, is_postfix_, is_increment_);
3558 __ CallStub(&stub); 3196 __ CallStub(&stub);
3559 } 3197 }
3560 3198
3561 3199
3562 void Ia32CodeGenerator::VisitCountOperation(CountOperation* node) { 3200 void CodeGenerator::VisitCountOperation(CountOperation* node) {
3563 Comment cmnt(masm_, "[ CountOperation"); 3201 Comment cmnt(masm_, "[ CountOperation");
3564 3202
3565 bool is_postfix = node->is_postfix(); 3203 bool is_postfix = node->is_postfix();
3566 bool is_increment = node->op() == Token::INC; 3204 bool is_increment = node->op() == Token::INC;
3567 3205
3568 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 3206 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
3569 bool is_const = (var != NULL && var->mode() == Variable::CONST); 3207 bool is_const = (var != NULL && var->mode() == Variable::CONST);
3570 3208
3571 // Postfix: Make room for the result. 3209 // Postfix: Make room for the result.
3572 if (is_postfix) __ push(Immediate(0)); 3210 if (is_postfix) __ push(Immediate(0));
(...skipping 30 matching lines...) Expand all
3603 __ bind(deferred->exit()); 3241 __ bind(deferred->exit());
3604 __ push(eax); // Push the new value to TOS 3242 __ push(eax); // Push the new value to TOS
3605 if (!is_const) target.SetValue(NOT_CONST_INIT); 3243 if (!is_const) target.SetValue(NOT_CONST_INIT);
3606 } 3244 }
3607 3245
3608 // Postfix: Discard the new value and use the old. 3246 // Postfix: Discard the new value and use the old.
3609 if (is_postfix) __ pop(eax); 3247 if (is_postfix) __ pop(eax);
3610 } 3248 }
3611 3249
3612 3250
3613 void Ia32CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 3251 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
3614 Comment cmnt(masm_, "[ BinaryOperation"); 3252 Comment cmnt(masm_, "[ BinaryOperation");
3615 Token::Value op = node->op(); 3253 Token::Value op = node->op();
3616 3254
3617 // According to ECMA-262 section 11.11, page 58, the binary logical 3255 // According to ECMA-262 section 11.11, page 58, the binary logical
3618 // operators must yield the result of one of the two expressions 3256 // operators must yield the result of one of the two expressions
3619 // before any ToBoolean() conversions. This means that the value 3257 // before any ToBoolean() conversions. This means that the value
3620 // produced by a && or || operator is not necessarily a boolean. 3258 // produced by a && or || operator is not necessarily a boolean.
3621 3259
3622 // NOTE: If the left hand side produces a materialized value (not in 3260 // NOTE: If the left hand side produces a materialized value (not in
3623 // the CC register), we force the right hand side to do the 3261 // the CC register), we force the right hand side to do the
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
3725 3363
3726 } else { 3364 } else {
3727 Load(node->left()); 3365 Load(node->left());
3728 Load(node->right()); 3366 Load(node->right());
3729 GenericBinaryOperation(node->op(), overwrite_mode); 3367 GenericBinaryOperation(node->op(), overwrite_mode);
3730 } 3368 }
3731 } 3369 }
3732 } 3370 }
3733 3371
3734 3372
3735 void Ia32CodeGenerator::VisitThisFunction(ThisFunction* node) { 3373 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
3736 __ push(FunctionOperand()); 3374 __ push(FunctionOperand());
3737 } 3375 }
3738 3376
3739 3377
3740 class InstanceofStub: public CodeStub { 3378 class InstanceofStub: public CodeStub {
3741 public: 3379 public:
3742 InstanceofStub() { } 3380 InstanceofStub() { }
3743 3381
3744 void Generate(MacroAssembler* masm); 3382 void Generate(MacroAssembler* masm);
3745 3383
3746 private: 3384 private:
3747 Major MajorKey() { return Instanceof; } 3385 Major MajorKey() { return Instanceof; }
3748 int MinorKey() { return 0; } 3386 int MinorKey() { return 0; }
3749 }; 3387 };
3750 3388
3751 3389
3752 void Ia32CodeGenerator::VisitCompareOperation(CompareOperation* node) { 3390 void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
3753 Comment cmnt(masm_, "[ CompareOperation"); 3391 Comment cmnt(masm_, "[ CompareOperation");
3754 3392
3755 // Get the expressions from the node. 3393 // Get the expressions from the node.
3756 Expression* left = node->left(); 3394 Expression* left = node->left();
3757 Expression* right = node->right(); 3395 Expression* right = node->right();
3758 Token::Value op = node->op(); 3396 Token::Value op = node->op();
3759 3397
3760 // NOTE: To make null checks efficient, we check if either left or 3398 // NOTE: To make null checks efficient, we check if either left or
3761 // right is the literal 'null'. If so, we optimize the code by 3399 // right is the literal 'null'. If so, we optimize the code by
3762 // inlining a null check instead of calling the (very) general 3400 // inlining a null check instead of calling the (very) general
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
3951 SmiComparison(cc, right->AsLiteral()->handle(), strict); 3589 SmiComparison(cc, right->AsLiteral()->handle(), strict);
3952 return; 3590 return;
3953 } 3591 }
3954 3592
3955 Load(left); 3593 Load(left);
3956 Load(right); 3594 Load(right);
3957 Comparison(cc, strict); 3595 Comparison(cc, strict);
3958 } 3596 }
3959 3597
3960 3598
3961 void Ia32CodeGenerator::RecordStatementPosition(Node* node) { 3599 void CodeGenerator::RecordStatementPosition(Node* node) {
3962 if (FLAG_debug_info) { 3600 if (FLAG_debug_info) {
3963 int pos = node->statement_pos(); 3601 int pos = node->statement_pos();
3964 if (pos != RelocInfo::kNoPosition) { 3602 if (pos != RelocInfo::kNoPosition) {
3965 __ RecordStatementPosition(pos); 3603 __ RecordStatementPosition(pos);
3966 } 3604 }
3967 } 3605 }
3968 } 3606 }
3969 3607
3970 3608
3971 void Ia32CodeGenerator::EnterJSFrame() { 3609 void CodeGenerator::EnterJSFrame() {
3972 __ push(ebp); 3610 __ push(ebp);
3973 __ mov(ebp, Operand(esp)); 3611 __ mov(ebp, Operand(esp));
3974 3612
3975 // Store the context and the function in the frame. 3613 // Store the context and the function in the frame.
3976 __ push(esi); 3614 __ push(esi);
3977 __ push(edi); 3615 __ push(edi);
3978 3616
3979 // Clear the function slot when generating debug code. 3617 // Clear the function slot when generating debug code.
3980 if (FLAG_debug_code) { 3618 if (FLAG_debug_code) {
3981 __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue))); 3619 __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue)));
3982 } 3620 }
3983 } 3621 }
3984 3622
3985 3623
3986 void Ia32CodeGenerator::ExitJSFrame() { 3624 void CodeGenerator::ExitJSFrame() {
3987 // Record the location of the JS exit code for patching when setting 3625 // Record the location of the JS exit code for patching when setting
3988 // break point. 3626 // break point.
3989 __ RecordJSReturn(); 3627 __ RecordJSReturn();
3990 3628
3991 // Avoid using the leave instruction here, because it is too 3629 // Avoid using the leave instruction here, because it is too
3992 // short. We need the return sequence to be a least the size of a 3630 // short. We need the return sequence to be a least the size of a
3993 // call instruction to support patching the exit code in the 3631 // call instruction to support patching the exit code in the
3994 // debugger. See VisitReturnStatement for the full return sequence. 3632 // debugger. See VisitReturnStatement for the full return sequence.
3995 __ mov(esp, Operand(ebp)); 3633 __ mov(esp, Operand(ebp));
3996 __ pop(ebp); 3634 __ pop(ebp);
(...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after
5336 __ ret(2 * kPointerSize); 4974 __ ret(2 * kPointerSize);
5337 4975
5338 // Slow-case: Go through the JavaScript implementation. 4976 // Slow-case: Go through the JavaScript implementation.
5339 __ bind(&slow); 4977 __ bind(&slow);
5340 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 4978 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5341 } 4979 }
5342 4980
5343 4981
5344 #undef __ 4982 #undef __
5345 4983
5346 // -----------------------------------------------------------------------------
5347 // CodeGenerator interfaces
5348
5349 // MakeCode() is just a wrapper for CodeGenerator::MakeCode()
5350 // so we don't have to expose the entire CodeGenerator class in
5351 // the .h file.
5352 Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
5353 Handle<Script> script,
5354 bool is_eval) {
5355 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval);
5356 if (!code.is_null()) {
5357 Counters::total_compiled_code_size.Increment(code->instruction_size());
5358 }
5359 return code;
5360 }
5361
5362
5363 } } // namespace v8::internal 4984 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | tools/v8.xcodeproj/project.pbxproj » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698