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

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

Issue 7076: Add a VirtualFrame class to the IA32 code generator. All frame... (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') | no next file » | 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 17 matching lines...) Expand all
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "bootstrapper.h" 30 #include "bootstrapper.h"
31 #include "codegen-inl.h" 31 #include "codegen-inl.h"
32 #include "debug.h" 32 #include "debug.h"
33 #include "scopes.h" 33 #include "scopes.h"
34 #include "runtime.h" 34 #include "runtime.h"
35 35
36 namespace v8 { namespace internal { 36 namespace v8 { namespace internal {
37 37
38 #define TOS (Operand(esp, 0)) 38 #define __ masm_->
39
40 // -------------------------------------------------------------------------
41 // VirtualFrame implementation.
42
43 VirtualFrame::VirtualFrame(CodeGenerator* cgen) {
44 ASSERT(cgen->scope() != NULL);
45
46 masm_ = cgen->masm();
47 frame_local_count_ = cgen->scope()->num_stack_slots();
48 parameter_count_ = cgen->scope()->num_parameters();
49 }
50
51
52 void VirtualFrame::AllocateLocals() {
53 if (frame_local_count_ > 0) {
54 Comment cmnt(masm_, "[ Allocate space for locals");
55 __ Set(eax, Immediate(Factory::undefined_value()));
56 for (int i = 0; i < frame_local_count_; i++) {
57 __ push(eax);
58 }
59 }
60 }
61
62
63 void VirtualFrame::Drop(int count) {
64 ASSERT(count >= 0);
65 if (count > 0) {
66 __ add(Operand(esp), Immediate(count * kPointerSize));
67 }
68 }
69
70
71 void VirtualFrame::Pop(Register reg) {
72 __ pop(reg);
73 }
74
75
76 void VirtualFrame::Pop(Operand operand) {
77 __ pop(operand);
78 }
79
80
81 void VirtualFrame::Push(Register reg) {
82 __ push(reg);
83 }
84
85
86 void VirtualFrame::Push(Operand operand) {
87 __ push(operand);
88 }
89
90
91 void VirtualFrame::Push(Immediate immediate) {
92 __ push(immediate);
93 }
39 94
40 95
41 // ------------------------------------------------------------------------- 96 // -------------------------------------------------------------------------
42 // CodeGenState implementation. 97 // CodeGenState implementation.
43 98
44 CodeGenState::CodeGenState(CodeGenerator* owner) 99 CodeGenState::CodeGenState(CodeGenerator* owner)
45 : owner_(owner), 100 : owner_(owner),
46 typeof_state_(NOT_INSIDE_TYPEOF), 101 typeof_state_(NOT_INSIDE_TYPEOF),
47 true_target_(NULL), 102 true_target_(NULL),
48 false_target_(NULL), 103 false_target_(NULL),
(...skipping 14 matching lines...) Expand all
63 owner_->set_state(this); 118 owner_->set_state(this);
64 } 119 }
65 120
66 121
67 CodeGenState::~CodeGenState() { 122 CodeGenState::~CodeGenState() {
68 ASSERT(owner_->state() == this); 123 ASSERT(owner_->state() == this);
69 owner_->set_state(previous_); 124 owner_->set_state(previous_);
70 } 125 }
71 126
72 127
73 // ----------------------------------------------------------------------------- 128 // -------------------------------------------------------------------------
74 // CodeGenerator implementation 129 // CodeGenerator implementation
75 130
76 #define __ masm_->
77
78 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, 131 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
79 bool is_eval) 132 bool is_eval)
80 : is_eval_(is_eval), 133 : is_eval_(is_eval),
81 script_(script), 134 script_(script),
82 deferred_(8), 135 deferred_(8),
83 masm_(new MacroAssembler(NULL, buffer_size)), 136 masm_(new MacroAssembler(NULL, buffer_size)),
84 scope_(NULL), 137 scope_(NULL),
138 frame_(NULL),
85 cc_reg_(no_condition), 139 cc_reg_(no_condition),
86 state_(NULL), 140 state_(NULL),
87 is_inside_try_(false), 141 is_inside_try_(false),
88 break_stack_height_(0) { 142 break_stack_height_(0) {
89 } 143 }
90 144
91 145
92 // Calling conventions: 146 // Calling conventions:
93 // ebp: frame pointer 147 // ebp: frame pointer
94 // esp: stack pointer 148 // esp: stack pointer
95 // edi: caller's parameter pointer 149 // edi: caller's parameter pointer
96 // esi: callee's context 150 // esi: callee's context
97 151
98 void CodeGenerator::GenCode(FunctionLiteral* fun) { 152 void CodeGenerator::GenCode(FunctionLiteral* fun) {
99 // Record the position for debugging purposes. 153 // Record the position for debugging purposes.
100 __ RecordPosition(fun->start_position()); 154 __ RecordPosition(fun->start_position());
101 155
102 Scope* scope = fun->scope();
103 ZoneList<Statement*>* body = fun->body(); 156 ZoneList<Statement*>* body = fun->body();
104 157
105 // Initialize state. 158 // Initialize state.
106 { CodeGenState state(this); 159 ASSERT(scope_ == NULL);
107 scope_ = scope; 160 scope_ = fun->scope();
108 cc_reg_ = no_condition; 161 ASSERT(frame_ == NULL);
162 VirtualFrame virtual_frame(this);
163 frame_ = &virtual_frame;
164 cc_reg_ = no_condition;
165 {
166 CodeGenState state(this);
109 167
110 // Entry 168 // Entry
111 // stack: function, receiver, arguments, return address 169 // stack: function, receiver, arguments, return address
112 // esp: stack pointer 170 // esp: stack pointer
113 // ebp: frame pointer 171 // ebp: frame pointer
114 // edi: caller's parameter pointer 172 // edi: caller's parameter pointer
115 // esi: callee's context 173 // esi: callee's context
116 174
117 { Comment cmnt(masm_, "[ enter JS frame"); 175 frame_->Enter();
118 EnterJSFrame();
119 }
120 // tos: code slot 176 // tos: code slot
121 #ifdef DEBUG 177 #ifdef DEBUG
122 if (strlen(FLAG_stop_at) > 0 && 178 if (strlen(FLAG_stop_at) > 0 &&
123 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 179 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
124 __ int3(); 180 __ int3();
125 } 181 }
126 #endif 182 #endif
127 183
128 // This section now only allocates and copies the formals into the 184 // This section now only allocates and copies the formals into the
129 // arguments object. It saves the address in ecx, which is saved 185 // arguments object. It saves the address in ecx, which is saved
130 // at any point before either garbage collection or ecx is 186 // at any point before either garbage collection or ecx is
131 // overwritten. The flag arguments_array_allocated communicates 187 // overwritten. The flag arguments_array_allocated communicates
132 // with the store into the arguments variable and guards the lazy 188 // with the store into the arguments variable and guards the lazy
133 // pushes of ecx to TOS. The flag arguments_array_saved notes 189 // pushes of ecx to TOS. The flag arguments_array_saved notes
134 // when the push has happened. 190 // when the push has happened.
135 bool arguments_object_allocated = false; 191 bool arguments_object_allocated = false;
136 bool arguments_object_saved = false; 192 bool arguments_object_saved = false;
137 193
138 // Allocate arguments object. 194 // Allocate arguments object.
139 // The arguments object pointer needs to be saved in ecx, since we need 195 // The arguments object pointer needs to be saved in ecx, since we need
140 // to store arguments into the context. 196 // to store arguments into the context.
141 if (scope->arguments() != NULL) { 197 if (scope_->arguments() != NULL) {
142 ASSERT(scope->arguments_shadow() != NULL); 198 ASSERT(scope_->arguments_shadow() != NULL);
143 Comment cmnt(masm_, "[ allocate arguments object"); 199 Comment cmnt(masm_, "[ allocate arguments object");
144 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 200 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
145 __ lea(eax, ReceiverOperand()); 201 __ lea(eax, frame_->Receiver());
146 __ push(FunctionOperand()); 202 frame_->Push(frame_->Function());
147 __ push(eax); 203 frame_->Push(eax);
148 __ push(Immediate(Smi::FromInt(scope->num_parameters()))); 204 frame_->Push(Immediate(Smi::FromInt(scope_->num_parameters())));
149 __ CallStub(&stub); 205 __ CallStub(&stub);
150 __ mov(ecx, Operand(eax)); 206 __ mov(ecx, Operand(eax));
151 arguments_object_allocated = true; 207 arguments_object_allocated = true;
152 } 208 }
153 209
154 // Allocate space for locals and initialize them. 210 // Allocate space for locals and initialize them.
155 if (scope->num_stack_slots() > 0) { 211 frame_->AllocateLocals();
156 Comment cmnt(masm_, "[ allocate space for locals");
157 __ Set(eax, Immediate(Factory::undefined_value()));
158 for (int i = scope->num_stack_slots(); i-- > 0; ) __ push(eax);
159 }
160 212
161 if (scope->num_heap_slots() > 0) { 213 if (scope_->num_heap_slots() > 0) {
162 Comment cmnt(masm_, "[ allocate local context"); 214 Comment cmnt(masm_, "[ allocate local context");
163 // Save the arguments object pointer, if any. 215 // Save the arguments object pointer, if any.
164 if (arguments_object_allocated && !arguments_object_saved) { 216 if (arguments_object_allocated && !arguments_object_saved) {
165 __ push(Operand(ecx)); 217 frame_->Push(ecx);
166 arguments_object_saved = true; 218 arguments_object_saved = true;
167 } 219 }
168 // Allocate local context. 220 // Allocate local context.
169 // Get outer context and create a new context based on it. 221 // Get outer context and create a new context based on it.
170 __ push(FunctionOperand()); 222 frame_->Push(frame_->Function());
171 __ CallRuntime(Runtime::kNewContext, 1); // eax holds the result 223 __ CallRuntime(Runtime::kNewContext, 1); // eax holds the result
172 224
173 if (kDebug) { 225 if (kDebug) {
174 Label verified_true; 226 Label verified_true;
175 // Verify eax and esi are the same in debug mode 227 // Verify eax and esi are the same in debug mode
176 __ cmp(eax, Operand(esi)); 228 __ cmp(eax, Operand(esi));
177 __ j(equal, &verified_true); 229 __ j(equal, &verified_true);
178 __ int3(); 230 __ int3();
179 __ bind(&verified_true); 231 __ bind(&verified_true);
180 } 232 }
181 233
182 // Update context local. 234 // Update context local.
183 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 235 __ mov(frame_->Context(), esi);
184 // Restore the arguments array pointer, if any. 236 // Restore the arguments array pointer, if any.
185 } 237 }
186 238
187 // TODO(1241774): Improve this code: 239 // TODO(1241774): Improve this code:
188 // 1) only needed if we have a context 240 // 1) only needed if we have a context
189 // 2) no need to recompute context ptr every single time 241 // 2) no need to recompute context ptr every single time
190 // 3) don't copy parameter operand code from SlotOperand! 242 // 3) don't copy parameter operand code from SlotOperand!
191 { 243 {
192 Comment cmnt2(masm_, "[ copy context parameters into .context"); 244 Comment cmnt2(masm_, "[ copy context parameters into .context");
193 245
194 // Note that iteration order is relevant here! If we have the same 246 // Note that iteration order is relevant here! If we have the same
195 // parameter twice (e.g., function (x, y, x)), and that parameter 247 // parameter twice (e.g., function (x, y, x)), and that parameter
196 // needs to be copied into the context, it must be the last argument 248 // needs to be copied into the context, it must be the last argument
197 // passed to the parameter that needs to be copied. This is a rare 249 // passed to the parameter that needs to be copied. This is a rare
198 // case so we don't check for it, instead we rely on the copying 250 // case so we don't check for it, instead we rely on the copying
199 // order: such a parameter is copied repeatedly into the same 251 // order: such a parameter is copied repeatedly into the same
200 // context location and thus the last value is what is seen inside 252 // context location and thus the last value is what is seen inside
201 // the function. 253 // the function.
202 for (int i = 0; i < scope->num_parameters(); i++) { 254 for (int i = 0; i < scope_->num_parameters(); i++) {
203 Variable* par = scope->parameter(i); 255 Variable* par = scope_->parameter(i);
204 Slot* slot = par->slot(); 256 Slot* slot = par->slot();
205 if (slot != NULL && slot->type() == Slot::CONTEXT) { 257 if (slot != NULL && slot->type() == Slot::CONTEXT) {
206 // Save the arguments object pointer, if any. 258 // Save the arguments object pointer, if any.
207 if (arguments_object_allocated && !arguments_object_saved) { 259 if (arguments_object_allocated && !arguments_object_saved) {
208 __ push(Operand(ecx)); 260 frame_->Push(ecx);
209 arguments_object_saved = true; 261 arguments_object_saved = true;
210 } 262 }
211 ASSERT(!scope->is_global_scope()); // no parameters in global scope 263 ASSERT(!scope_->is_global_scope()); // no parameters in global scope
212 __ mov(eax, ParameterOperand(i)); 264 __ mov(eax, frame_->Parameter(i));
213 // Loads ecx with context; used below in RecordWrite. 265 // Loads ecx with context; used below in RecordWrite.
214 __ mov(SlotOperand(slot, ecx), eax); 266 __ mov(SlotOperand(slot, ecx), eax);
215 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 267 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
216 __ RecordWrite(ecx, offset, eax, ebx); 268 __ RecordWrite(ecx, offset, eax, ebx);
217 } 269 }
218 } 270 }
219 } 271 }
220 272
221 // This section stores the pointer to the arguments object that 273 // This section stores the pointer to the arguments object that
222 // was allocated and copied into above. If the address was not 274 // was allocated and copied into above. If the address was not
223 // saved to TOS, we push ecx onto the stack. 275 // saved to TOS, we push ecx onto the stack.
224 276
225 // Store the arguments object. 277 // Store the arguments object.
226 // This must happen after context initialization because 278 // This must happen after context initialization because
227 // the arguments object may be stored in the context 279 // the arguments object may be stored in the context
228 if (arguments_object_allocated) { 280 if (arguments_object_allocated) {
229 ASSERT(scope->arguments() != NULL); 281 ASSERT(scope_->arguments() != NULL);
230 ASSERT(scope->arguments_shadow() != NULL); 282 ASSERT(scope_->arguments_shadow() != NULL);
231 Comment cmnt(masm_, "[ store arguments object"); 283 Comment cmnt(masm_, "[ store arguments object");
232 { Reference shadow_ref(this, scope->arguments_shadow()); 284 { Reference shadow_ref(this, scope_->arguments_shadow());
233 ASSERT(shadow_ref.is_slot()); 285 ASSERT(shadow_ref.is_slot());
234 { Reference arguments_ref(this, scope->arguments()); 286 { Reference arguments_ref(this, scope_->arguments());
235 ASSERT(arguments_ref.is_slot()); 287 ASSERT(arguments_ref.is_slot());
236 // If the newly-allocated arguments object is already on the 288 // If the newly-allocated arguments object is already on the
237 // stack, we make use of the convenient property that references 289 // stack, we make use of the convenient property that references
238 // representing slots take up no space on the expression stack 290 // representing slots take up no space on the expression stack
239 // (ie, it doesn't matter that the stored value is actually below 291 // (ie, it doesn't matter that the stored value is actually below
240 // the reference). 292 // the reference).
241 // 293 //
242 // If the newly-allocated argument object is not already on 294 // If the newly-allocated argument object is not already on
243 // the stack, we rely on the property that loading a 295 // the stack, we rely on the property that loading a
244 // zero-sized reference will not clobber the ecx register. 296 // zero-sized reference will not clobber the ecx register.
245 if (!arguments_object_saved) { 297 if (!arguments_object_saved) {
246 __ push(ecx); 298 frame_->Push(ecx);
247 } 299 }
248 arguments_ref.SetValue(NOT_CONST_INIT); 300 arguments_ref.SetValue(NOT_CONST_INIT);
249 } 301 }
250 shadow_ref.SetValue(NOT_CONST_INIT); 302 shadow_ref.SetValue(NOT_CONST_INIT);
251 } 303 }
252 __ pop(eax); // Value is no longer needed. 304 frame_->Pop(eax); // Value is no longer needed.
iposva 2008/10/10 12:53:02 If the value is really no longer needed the there
253 } 305 }
254 306
255 // Generate code to 'execute' declarations and initialize 307 // Generate code to 'execute' declarations and initialize
256 // functions (source elements). In case of an illegal 308 // functions (source elements). In case of an illegal
257 // redeclaration we need to handle that instead of processing the 309 // redeclaration we need to handle that instead of processing the
258 // declarations. 310 // declarations.
259 if (scope->HasIllegalRedeclaration()) { 311 if (scope_->HasIllegalRedeclaration()) {
260 Comment cmnt(masm_, "[ illegal redeclarations"); 312 Comment cmnt(masm_, "[ illegal redeclarations");
261 scope->VisitIllegalRedeclaration(this); 313 scope_->VisitIllegalRedeclaration(this);
262 } else { 314 } else {
263 Comment cmnt(masm_, "[ declarations"); 315 Comment cmnt(masm_, "[ declarations");
264 ProcessDeclarations(scope->declarations()); 316 ProcessDeclarations(scope_->declarations());
265 // Bail out if a stack-overflow exception occurred when 317 // Bail out if a stack-overflow exception occurred when
266 // processing declarations. 318 // processing declarations.
267 if (HasStackOverflow()) return; 319 if (HasStackOverflow()) return;
268 } 320 }
269 321
270 if (FLAG_trace) { 322 if (FLAG_trace) {
271 __ CallRuntime(Runtime::kTraceEnter, 1); 323 __ CallRuntime(Runtime::kTraceEnter, 1);
272 __ push(eax); 324 frame_->Push(eax);
273 } 325 }
274 CheckStack(); 326 CheckStack();
275 327
276 // Compile the body of the function in a vanilla state. Don't 328 // Compile the body of the function in a vanilla state. Don't
277 // bother compiling all the code if the scope has an illegal 329 // bother compiling all the code if the scope has an illegal
278 // redeclaration. 330 // redeclaration.
279 if (!scope->HasIllegalRedeclaration()) { 331 if (!scope_->HasIllegalRedeclaration()) {
280 Comment cmnt(masm_, "[ function body"); 332 Comment cmnt(masm_, "[ function body");
281 #ifdef DEBUG 333 #ifdef DEBUG
282 bool is_builtin = Bootstrapper::IsActive(); 334 bool is_builtin = Bootstrapper::IsActive();
283 bool should_trace = 335 bool should_trace =
284 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; 336 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
285 if (should_trace) { 337 if (should_trace) {
286 __ CallRuntime(Runtime::kDebugTrace, 1); 338 __ CallRuntime(Runtime::kDebugTrace, 1);
287 __ push(eax); 339 frame_->Push(eax);
288 } 340 }
289 #endif 341 #endif
290 VisitStatements(body); 342 VisitStatements(body);
291 343
292 // Generate a return statement if necessary. 344 // Generate a return statement if necessary.
293 if (body->is_empty() || body->last()->AsReturnStatement() == NULL) { 345 if (body->is_empty() || body->last()->AsReturnStatement() == NULL) {
294 Literal undefined(Factory::undefined_value()); 346 Literal undefined(Factory::undefined_value());
295 ReturnStatement statement(&undefined); 347 ReturnStatement statement(&undefined);
296 statement.set_statement_pos(fun->end_position()); 348 statement.set_statement_pos(fun->end_position());
297 VisitReturnStatement(&statement); 349 VisitReturnStatement(&statement);
298 } 350 }
299 } 351 }
300 } 352 }
301 353
302 // Code generation state must be reset. 354 // Code generation state must be reset.
303 scope_ = NULL; 355 scope_ = NULL;
356 frame_ = NULL;
304 ASSERT(!has_cc()); 357 ASSERT(!has_cc());
305 ASSERT(state_ == NULL); 358 ASSERT(state_ == NULL);
306 } 359 }
307 360
308 361
309 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { 362 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
310 // Currently, this assertion will fail if we try to assign to 363 // Currently, this assertion will fail if we try to assign to
311 // a constant variable that is constant because it is read-only 364 // a constant variable that is constant because it is read-only
312 // (such as the variable referring to a named function expression). 365 // (such as the variable referring to a named function expression).
313 // We need to implement assignments to read-only variables. 366 // We need to implement assignments to read-only variables.
314 // Ideally, we should do this during AST generation (by converting 367 // Ideally, we should do this during AST generation (by converting
315 // such assignments into expression statements); however, in general 368 // such assignments into expression statements); however, in general
316 // we may not be able to make the decision until past AST generation, 369 // we may not be able to make the decision until past AST generation,
317 // that is when the entire program is known. 370 // that is when the entire program is known.
318 ASSERT(slot != NULL); 371 ASSERT(slot != NULL);
319 int index = slot->index(); 372 int index = slot->index();
320 switch (slot->type()) { 373 switch (slot->type()) {
321 case Slot::PARAMETER: 374 case Slot::PARAMETER:
322 return ParameterOperand(index); 375 return frame_->Parameter(index);
323 376
324 case Slot::LOCAL: { 377 case Slot::LOCAL:
325 ASSERT(0 <= index && index < scope()->num_stack_slots()); 378 return frame_->Local(index);
326 const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
327 return Operand(ebp, kLocal0Offset - index * kPointerSize);
328 }
329 379
330 case Slot::CONTEXT: { 380 case Slot::CONTEXT: {
331 // Follow the context chain if necessary. 381 // Follow the context chain if necessary.
332 ASSERT(!tmp.is(esi)); // do not overwrite context register 382 ASSERT(!tmp.is(esi)); // do not overwrite context register
333 Register context = esi; 383 Register context = esi;
334 int chain_length = scope()->ContextChainLength(slot->var()->scope()); 384 int chain_length = scope()->ContextChainLength(slot->var()->scope());
335 for (int i = chain_length; i-- > 0;) { 385 for (int i = chain_length; i-- > 0;) {
336 // Load the closure. 386 // Load the closure.
337 // (All contexts, even 'with' contexts, have a closure, 387 // (All contexts, even 'with' contexts, have a closure,
338 // and it is the same for all contexts inside a function. 388 // and it is the same for all contexts inside a function.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 435 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
386 Label true_target; 436 Label true_target;
387 Label false_target; 437 Label false_target;
388 LoadCondition(x, typeof_state, &true_target, &false_target, false); 438 LoadCondition(x, typeof_state, &true_target, &false_target, false);
389 439
390 if (has_cc()) { 440 if (has_cc()) {
391 // convert cc_reg_ into a bool 441 // convert cc_reg_ into a bool
392 442
393 Label loaded, materialize_true; 443 Label loaded, materialize_true;
394 __ j(cc_reg_, &materialize_true); 444 __ j(cc_reg_, &materialize_true);
395 __ push(Immediate(Factory::false_value())); 445 frame_->Push(Immediate(Factory::false_value()));
396 __ jmp(&loaded); 446 __ jmp(&loaded);
397 __ bind(&materialize_true); 447 __ bind(&materialize_true);
398 __ push(Immediate(Factory::true_value())); 448 frame_->Push(Immediate(Factory::true_value()));
399 __ bind(&loaded); 449 __ bind(&loaded);
400 cc_reg_ = no_condition; 450 cc_reg_ = no_condition;
401 } 451 }
402 452
403 if (true_target.is_linked() || false_target.is_linked()) { 453 if (true_target.is_linked() || false_target.is_linked()) {
404 // we have at least one condition value 454 // we have at least one condition value
405 // that has been "translated" into a branch, 455 // that has been "translated" into a branch,
406 // thus it needs to be loaded explicitly again 456 // thus it needs to be loaded explicitly again
407 Label loaded; 457 Label loaded;
408 __ jmp(&loaded); // don't lose current TOS 458 __ jmp(&loaded); // don't lose current TOS
409 bool both = true_target.is_linked() && false_target.is_linked(); 459 bool both = true_target.is_linked() && false_target.is_linked();
410 // reincarnate "true", if necessary 460 // reincarnate "true", if necessary
411 if (true_target.is_linked()) { 461 if (true_target.is_linked()) {
412 __ bind(&true_target); 462 __ bind(&true_target);
413 __ push(Immediate(Factory::true_value())); 463 frame_->Push(Immediate(Factory::true_value()));
414 } 464 }
415 // if both "true" and "false" need to be reincarnated, 465 // if both "true" and "false" need to be reincarnated,
416 // jump across code for "false" 466 // jump across code for "false"
417 if (both) 467 if (both)
418 __ jmp(&loaded); 468 __ jmp(&loaded);
419 // reincarnate "false", if necessary 469 // reincarnate "false", if necessary
420 if (false_target.is_linked()) { 470 if (false_target.is_linked()) {
421 __ bind(&false_target); 471 __ bind(&false_target);
422 __ push(Immediate(Factory::false_value())); 472 frame_->Push(Immediate(Factory::false_value()));
423 } 473 }
424 // everything is loaded at this point 474 // everything is loaded at this point
425 __ bind(&loaded); 475 __ bind(&loaded);
426 } 476 }
427 ASSERT(!has_cc()); 477 ASSERT(!has_cc());
428 } 478 }
429 479
430 480
431 void CodeGenerator::LoadGlobal() { 481 void CodeGenerator::LoadGlobal() {
432 __ push(GlobalObject()); 482 frame_->Push(GlobalObject());
433 } 483 }
434 484
435 485
436 // TODO(1241834): Get rid of this function in favor of just using Load, now 486 // TODO(1241834): Get rid of this function in favor of just using Load, now
437 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global 487 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global
438 // variables w/o reference errors elsewhere. 488 // variables w/o reference errors elsewhere.
439 void CodeGenerator::LoadTypeofExpression(Expression* x) { 489 void CodeGenerator::LoadTypeofExpression(Expression* x) {
440 Variable* variable = x->AsVariableProxy()->AsVariable(); 490 Variable* variable = x->AsVariableProxy()->AsVariable();
441 if (variable != NULL && !variable->is_this() && variable->is_global()) { 491 if (variable != NULL && !variable->is_this() && variable->is_global()) {
442 // NOTE: This is somewhat nasty. We force the compiler to load 492 // NOTE: This is somewhat nasty. We force the compiler to load
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 } 557 }
508 558
509 559
510 void CodeGenerator::UnloadReference(Reference* ref) { 560 void CodeGenerator::UnloadReference(Reference* ref) {
511 // Pop a reference from the stack while preserving TOS. 561 // Pop a reference from the stack while preserving TOS.
512 Comment cmnt(masm_, "[ UnloadReference"); 562 Comment cmnt(masm_, "[ UnloadReference");
513 int size = ref->size(); 563 int size = ref->size();
514 if (size <= 0) { 564 if (size <= 0) {
515 // Do nothing. No popping is necessary. 565 // Do nothing. No popping is necessary.
516 } else if (size == 1) { 566 } else if (size == 1) {
517 __ pop(eax); 567 frame_->Pop(eax);
518 __ mov(TOS, eax); 568 __ mov(frame_->Top(), eax);
519 } else { 569 } else {
520 __ pop(eax); 570 frame_->Pop(eax);
521 __ add(Operand(esp), Immediate(size * kPointerSize)); 571 frame_->Drop(size);
522 __ push(eax); 572 frame_->Push(eax);
523 } 573 }
524 } 574 }
525 575
526 576
527 class ToBooleanStub: public CodeStub { 577 class ToBooleanStub: public CodeStub {
528 public: 578 public:
529 ToBooleanStub() { } 579 ToBooleanStub() { }
530 580
531 void Generate(MacroAssembler* masm); 581 void Generate(MacroAssembler* masm);
532 582
533 private: 583 private:
534 Major MajorKey() { return ToBoolean; } 584 Major MajorKey() { return ToBoolean; }
535 int MinorKey() { return 0; } 585 int MinorKey() { return 0; }
536 }; 586 };
537 587
538 588
539 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and 589 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and
540 // convert it to a boolean in the condition code register or jump to 590 // convert it to a boolean in the condition code register or jump to
541 // 'false_target'/'true_target' as appropriate. 591 // 'false_target'/'true_target' as appropriate.
542 void CodeGenerator::ToBoolean(Label* true_target, Label* false_target) { 592 void CodeGenerator::ToBoolean(Label* true_target, Label* false_target) {
543 Comment cmnt(masm_, "[ ToBoolean"); 593 Comment cmnt(masm_, "[ ToBoolean");
544 594
545 // The value to convert should be popped from the stack. 595 // The value to convert should be popped from the stack.
546 __ pop(eax); 596 frame_->Pop(eax);
547 597
548 // Fast case checks. 598 // Fast case checks.
549 599
550 // 'false' => false. 600 // 'false' => false.
551 __ cmp(eax, Factory::false_value()); 601 __ cmp(eax, Factory::false_value());
552 __ j(equal, false_target); 602 __ j(equal, false_target);
553 603
554 // 'true' => true. 604 // 'true' => true.
555 __ cmp(eax, Factory::true_value()); 605 __ cmp(eax, Factory::true_value());
556 __ j(equal, true_target); 606 __ j(equal, true_target);
557 607
558 // 'undefined' => false. 608 // 'undefined' => false.
559 __ cmp(eax, Factory::undefined_value()); 609 __ cmp(eax, Factory::undefined_value());
560 __ j(equal, false_target); 610 __ j(equal, false_target);
561 611
562 // Smi => false iff zero. 612 // Smi => false iff zero.
563 ASSERT(kSmiTag == 0); 613 ASSERT(kSmiTag == 0);
564 __ test(eax, Operand(eax)); 614 __ test(eax, Operand(eax));
565 __ j(zero, false_target); 615 __ j(zero, false_target);
566 __ test(eax, Immediate(kSmiTagMask)); 616 __ test(eax, Immediate(kSmiTagMask));
567 __ j(zero, true_target); 617 __ j(zero, true_target);
568 618
569 // Call the stub for all other cases. 619 // Call the stub for all other cases.
570 __ push(eax); // Undo the pop(eax) from above. 620 frame_->Push(eax); // Undo the pop(eax) from above.
571 ToBooleanStub stub; 621 ToBooleanStub stub;
572 __ CallStub(&stub); 622 __ CallStub(&stub);
573 // Convert result (eax) to condition code. 623 // Convert result (eax) to condition code.
574 __ test(eax, Operand(eax)); 624 __ test(eax, Operand(eax));
575 625
576 ASSERT(not_equal == not_zero); 626 ASSERT(not_equal == not_zero);
577 cc_reg_ = not_equal; 627 cc_reg_ = not_equal;
578 } 628 }
579 629
580 630
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 Comment cmnt(masm_, "[ BinaryOperation"); 705 Comment cmnt(masm_, "[ BinaryOperation");
656 Comment cmnt_token(masm_, Token::String(op)); 706 Comment cmnt_token(masm_, Token::String(op));
657 switch (op) { 707 switch (op) {
658 case Token::ADD: 708 case Token::ADD:
659 case Token::SUB: 709 case Token::SUB:
660 case Token::MUL: 710 case Token::MUL:
661 case Token::DIV: 711 case Token::DIV:
662 case Token::MOD: { 712 case Token::MOD: {
663 GenericBinaryOpStub stub(op, overwrite_mode); 713 GenericBinaryOpStub stub(op, overwrite_mode);
664 __ CallStub(&stub); 714 __ CallStub(&stub);
665 __ push(eax); 715 frame_->Push(eax);
666 break; 716 break;
667 } 717 }
668 case Token::BIT_OR: 718 case Token::BIT_OR:
669 case Token::BIT_AND: 719 case Token::BIT_AND:
670 case Token::BIT_XOR: { 720 case Token::BIT_XOR: {
671 Label slow, exit; 721 Label slow, exit;
672 __ pop(eax); // get y 722 frame_->Pop(eax); // get y
673 __ pop(edx); // get x 723 frame_->Pop(edx); // get x
674 __ mov(ecx, Operand(edx)); // Prepare smi check. 724 __ mov(ecx, Operand(edx)); // Prepare smi check.
675 // tag check 725 // tag check
676 __ or_(ecx, Operand(eax)); // ecx = x | y; 726 __ or_(ecx, Operand(eax)); // ecx = x | y;
677 ASSERT(kSmiTag == 0); // adjust code below 727 ASSERT(kSmiTag == 0); // adjust code below
678 __ test(ecx, Immediate(kSmiTagMask)); 728 __ test(ecx, Immediate(kSmiTagMask));
679 __ j(not_zero, &slow, taken); 729 __ j(not_zero, &slow, taken);
680 switch (op) { 730 switch (op) {
681 case Token::BIT_OR: __ or_(eax, Operand(edx)); break; 731 case Token::BIT_OR: __ or_(eax, Operand(edx)); break;
682 case Token::BIT_AND: __ and_(eax, Operand(edx)); break; 732 case Token::BIT_AND: __ and_(eax, Operand(edx)); break;
683 case Token::BIT_XOR: __ xor_(eax, Operand(edx)); break; 733 case Token::BIT_XOR: __ xor_(eax, Operand(edx)); break;
684 default: UNREACHABLE(); 734 default: UNREACHABLE();
685 } 735 }
686 __ jmp(&exit); 736 __ jmp(&exit);
687 __ bind(&slow); 737 __ bind(&slow);
688 __ push(edx); // restore stack slots 738 frame_->Push(edx); // restore stack slots
689 __ push(eax); 739 frame_->Push(eax);
690 GenericBinaryOpStub stub(op, overwrite_mode); 740 GenericBinaryOpStub stub(op, overwrite_mode);
691 __ CallStub(&stub); 741 __ CallStub(&stub);
692 __ bind(&exit); 742 __ bind(&exit);
693 __ push(eax); // push the result to the stack 743 frame_->Push(eax); // push the result to the stack
694 break; 744 break;
695 } 745 }
696 case Token::SHL: 746 case Token::SHL:
697 case Token::SHR: 747 case Token::SHR:
698 case Token::SAR: { 748 case Token::SAR: {
699 Label slow, exit; 749 Label slow, exit;
700 __ pop(edx); // get y 750 frame_->Pop(edx); // get y
701 __ pop(eax); // get x 751 frame_->Pop(eax); // get x
702 // tag check 752 // tag check
703 __ mov(ecx, Operand(edx)); 753 __ mov(ecx, Operand(edx));
704 __ or_(ecx, Operand(eax)); // ecx = x | y; 754 __ or_(ecx, Operand(eax)); // ecx = x | y;
705 ASSERT(kSmiTag == 0); // adjust code below 755 ASSERT(kSmiTag == 0); // adjust code below
706 __ test(ecx, Immediate(kSmiTagMask)); 756 __ test(ecx, Immediate(kSmiTagMask));
707 __ j(not_zero, &slow, not_taken); 757 __ j(not_zero, &slow, not_taken);
708 // get copies of operands 758 // get copies of operands
709 __ mov(ebx, Operand(eax)); 759 __ mov(ebx, Operand(eax));
710 __ mov(ecx, Operand(edx)); 760 __ mov(ecx, Operand(edx));
711 // remove tags from operands (but keep sign) 761 // remove tags from operands (but keep sign)
(...skipping 24 matching lines...) Expand all
736 __ j(not_zero, &slow, not_taken); 786 __ j(not_zero, &slow, not_taken);
737 break; 787 break;
738 default: UNREACHABLE(); 788 default: UNREACHABLE();
739 } 789 }
740 // tag result and store it in TOS (eax) 790 // tag result and store it in TOS (eax)
741 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 791 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
742 __ lea(eax, Operand(ebx, times_2, kSmiTag)); 792 __ lea(eax, Operand(ebx, times_2, kSmiTag));
743 __ jmp(&exit); 793 __ jmp(&exit);
744 // slow case 794 // slow case
745 __ bind(&slow); 795 __ bind(&slow);
746 __ push(eax); // restore stack 796 frame_->Push(eax); // restore stack
747 __ push(edx); 797 frame_->Push(edx);
748 GenericBinaryOpStub stub(op, overwrite_mode); 798 GenericBinaryOpStub stub(op, overwrite_mode);
749 __ CallStub(&stub); 799 __ CallStub(&stub);
750 __ bind(&exit); 800 __ bind(&exit);
751 __ push(eax); 801 frame_->Push(eax);
752 break; 802 break;
753 } 803 }
754 case Token::COMMA: { 804 case Token::COMMA: {
755 // simply discard left value 805 // simply discard left value
756 __ pop(eax); 806 frame_->Pop(eax);
757 __ add(Operand(esp), Immediate(kPointerSize)); 807 frame_->Drop(1);
758 __ push(eax); 808 frame_->Push(eax);
759 break; 809 break;
760 } 810 }
761 default: UNREACHABLE(); 811 default: UNREACHABLE();
762 } 812 }
763 } 813 }
764 814
765 815
766 class DeferredInlinedSmiOperation: public DeferredCode { 816 class DeferredInlinedSmiOperation: public DeferredCode {
767 public: 817 public:
768 DeferredInlinedSmiOperation(CodeGenerator* generator, 818 DeferredInlinedSmiOperation(CodeGenerator* generator,
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
889 OverwriteMode overwrite_mode) : 939 OverwriteMode overwrite_mode) :
890 DeferredCode(generator), tos_reg_(tos_reg), 940 DeferredCode(generator), tos_reg_(tos_reg),
891 overwrite_mode_(overwrite_mode) { 941 overwrite_mode_(overwrite_mode) {
892 set_comment("[ DeferredInlinedSmiSubReversed"); 942 set_comment("[ DeferredInlinedSmiSubReversed");
893 } 943 }
894 944
895 virtual void Generate() { 945 virtual void Generate() {
896 // Undo the optimistic sub operation and call the shared stub. 946 // Undo the optimistic sub operation and call the shared stub.
897 __ add(eax, Operand(tos_reg_)); 947 __ add(eax, Operand(tos_reg_));
898 __ push(eax); 948 __ push(eax);
899 __ push(Operand(tos_reg_)); 949 __ push(tos_reg_);
900 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_); 950 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_);
901 __ CallStub(&igostub); 951 __ CallStub(&igostub);
902 } 952 }
903 953
904 private: 954 private:
905 Register tos_reg_; 955 Register tos_reg_;
906 OverwriteMode overwrite_mode_; 956 OverwriteMode overwrite_mode_;
907 }; 957 };
908 958
909 959
910 void CodeGenerator::SmiOperation(Token::Value op, 960 void CodeGenerator::SmiOperation(Token::Value op,
911 Handle<Object> value, 961 Handle<Object> value,
912 bool reversed, 962 bool reversed,
913 OverwriteMode overwrite_mode) { 963 OverwriteMode overwrite_mode) {
914 // NOTE: This is an attempt to inline (a bit) more of the code for 964 // NOTE: This is an attempt to inline (a bit) more of the code for
915 // some possible smi operations (like + and -) when (at least) one 965 // some possible smi operations (like + and -) when (at least) one
916 // of the operands is a literal smi. With this optimization, the 966 // of the operands is a literal smi. With this optimization, the
917 // performance of the system is increased by ~15%, and the generated 967 // performance of the system is increased by ~15%, and the generated
918 // code size is increased by ~1% (measured on a combination of 968 // code size is increased by ~1% (measured on a combination of
919 // different benchmarks). 969 // different benchmarks).
920 970
921 // TODO(1217802): Optimize some special cases of operations 971 // TODO(1217802): Optimize some special cases of operations
922 // involving a smi literal (multiply by 2, shift by 0, etc.). 972 // involving a smi literal (multiply by 2, shift by 0, etc.).
923 973
924 // Get the literal value. 974 // Get the literal value.
925 int int_value = Smi::cast(*value)->value(); 975 int int_value = Smi::cast(*value)->value();
926 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); 976 ASSERT(is_intn(int_value, kMaxSmiInlinedBits));
927 977
928 switch (op) { 978 switch (op) {
929 case Token::ADD: { 979 case Token::ADD: {
930 DeferredCode* deferred = NULL; 980 DeferredCode* deferred = NULL;
931 if (!reversed) { 981 if (!reversed) {
932 deferred = new DeferredInlinedSmiAdd(this, int_value, overwrite_mode); 982 deferred = new DeferredInlinedSmiAdd(this, int_value, overwrite_mode);
933 } else { 983 } else {
934 deferred = new DeferredInlinedSmiAddReversed(this, int_value, 984 deferred = new DeferredInlinedSmiAddReversed(this, int_value,
935 overwrite_mode); 985 overwrite_mode);
936 } 986 }
937 __ pop(eax); 987 frame_->Pop(eax);
938 __ add(Operand(eax), Immediate(value)); 988 __ add(Operand(eax), Immediate(value));
939 __ j(overflow, deferred->enter(), not_taken); 989 __ j(overflow, deferred->enter(), not_taken);
940 __ test(eax, Immediate(kSmiTagMask)); 990 __ test(eax, Immediate(kSmiTagMask));
941 __ j(not_zero, deferred->enter(), not_taken); 991 __ j(not_zero, deferred->enter(), not_taken);
942 __ bind(deferred->exit()); 992 __ bind(deferred->exit());
943 __ push(eax); 993 frame_->Push(eax);
944 break; 994 break;
945 } 995 }
946 996
947 case Token::SUB: { 997 case Token::SUB: {
948 DeferredCode* deferred = NULL; 998 DeferredCode* deferred = NULL;
949 __ pop(eax); 999 frame_->Pop(eax);
950 if (!reversed) { 1000 if (!reversed) {
951 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode); 1001 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode);
952 __ sub(Operand(eax), Immediate(value)); 1002 __ sub(Operand(eax), Immediate(value));
953 } else { 1003 } else {
954 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode); 1004 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode);
955 __ mov(edx, Operand(eax)); 1005 __ mov(edx, Operand(eax));
956 __ mov(Operand(eax), Immediate(value)); 1006 __ mov(Operand(eax), Immediate(value));
957 __ sub(eax, Operand(edx)); 1007 __ sub(eax, Operand(edx));
958 } 1008 }
959 __ j(overflow, deferred->enter(), not_taken); 1009 __ j(overflow, deferred->enter(), not_taken);
960 __ test(eax, Immediate(kSmiTagMask)); 1010 __ test(eax, Immediate(kSmiTagMask));
961 __ j(not_zero, deferred->enter(), not_taken); 1011 __ j(not_zero, deferred->enter(), not_taken);
962 __ bind(deferred->exit()); 1012 __ bind(deferred->exit());
963 __ push(eax); 1013 frame_->Push(eax);
964 break; 1014 break;
965 } 1015 }
966 1016
967 case Token::SAR: { 1017 case Token::SAR: {
968 if (reversed) { 1018 if (reversed) {
969 __ pop(eax); 1019 frame_->Pop(eax);
970 __ push(Immediate(value)); 1020 frame_->Push(Immediate(value));
971 __ push(eax); 1021 frame_->Push(eax);
972 GenericBinaryOperation(op, overwrite_mode); 1022 GenericBinaryOperation(op, overwrite_mode);
973 } else { 1023 } else {
974 int shift_value = int_value & 0x1f; // only least significant 5 bits 1024 int shift_value = int_value & 0x1f; // only least significant 5 bits
975 DeferredCode* deferred = 1025 DeferredCode* deferred =
976 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, 1026 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value,
977 overwrite_mode); 1027 overwrite_mode);
978 __ pop(eax); 1028 frame_->Pop(eax);
979 __ test(eax, Immediate(kSmiTagMask)); 1029 __ test(eax, Immediate(kSmiTagMask));
980 __ j(not_zero, deferred->enter(), not_taken); 1030 __ j(not_zero, deferred->enter(), not_taken);
981 __ sar(eax, shift_value); 1031 __ sar(eax, shift_value);
982 __ and_(eax, ~kSmiTagMask); 1032 __ and_(eax, ~kSmiTagMask);
983 __ bind(deferred->exit()); 1033 __ bind(deferred->exit());
984 __ push(eax); 1034 frame_->Push(eax);
985 } 1035 }
986 break; 1036 break;
987 } 1037 }
988 1038
989 case Token::SHR: { 1039 case Token::SHR: {
990 if (reversed) { 1040 if (reversed) {
991 __ pop(eax); 1041 frame_->Pop(eax);
992 __ push(Immediate(value)); 1042 frame_->Push(Immediate(value));
993 __ push(eax); 1043 frame_->Push(eax);
994 GenericBinaryOperation(op, overwrite_mode); 1044 GenericBinaryOperation(op, overwrite_mode);
995 } else { 1045 } else {
996 int shift_value = int_value & 0x1f; // only least significant 5 bits 1046 int shift_value = int_value & 0x1f; // only least significant 5 bits
997 DeferredCode* deferred = 1047 DeferredCode* deferred =
998 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, 1048 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value,
999 overwrite_mode); 1049 overwrite_mode);
1000 __ pop(eax); 1050 frame_->Pop(eax);
1001 __ test(eax, Immediate(kSmiTagMask)); 1051 __ test(eax, Immediate(kSmiTagMask));
1002 __ mov(ebx, Operand(eax)); 1052 __ mov(ebx, Operand(eax));
1003 __ j(not_zero, deferred->enter(), not_taken); 1053 __ j(not_zero, deferred->enter(), not_taken);
1004 __ sar(ebx, kSmiTagSize); 1054 __ sar(ebx, kSmiTagSize);
1005 __ shr(ebx, shift_value); 1055 __ shr(ebx, shift_value);
1006 __ test(ebx, Immediate(0xc0000000)); 1056 __ test(ebx, Immediate(0xc0000000));
1007 __ j(not_zero, deferred->enter(), not_taken); 1057 __ j(not_zero, deferred->enter(), not_taken);
1008 // tag result and store it in TOS (eax) 1058 // tag result and store it in TOS (eax)
1009 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1059 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
1010 __ lea(eax, Operand(ebx, times_2, kSmiTag)); 1060 __ lea(eax, Operand(ebx, times_2, kSmiTag));
1011 __ bind(deferred->exit()); 1061 __ bind(deferred->exit());
1012 __ push(eax); 1062 frame_->Push(eax);
1013 } 1063 }
1014 break; 1064 break;
1015 } 1065 }
1016 1066
1017 case Token::SHL: { 1067 case Token::SHL: {
1018 if (reversed) { 1068 if (reversed) {
1019 __ pop(eax); 1069 frame_->Pop(eax);
1020 __ push(Immediate(value)); 1070 frame_->Push(Immediate(value));
1021 __ push(eax); 1071 frame_->Push(eax);
1022 GenericBinaryOperation(op, overwrite_mode); 1072 GenericBinaryOperation(op, overwrite_mode);
1023 } else { 1073 } else {
1024 int shift_value = int_value & 0x1f; // only least significant 5 bits 1074 int shift_value = int_value & 0x1f; // only least significant 5 bits
1025 DeferredCode* deferred = 1075 DeferredCode* deferred =
1026 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, 1076 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value,
1027 overwrite_mode); 1077 overwrite_mode);
1028 __ pop(eax); 1078 frame_->Pop(eax);
1029 __ test(eax, Immediate(kSmiTagMask)); 1079 __ test(eax, Immediate(kSmiTagMask));
1030 __ mov(ebx, Operand(eax)); 1080 __ mov(ebx, Operand(eax));
1031 __ j(not_zero, deferred->enter(), not_taken); 1081 __ j(not_zero, deferred->enter(), not_taken);
1032 __ sar(ebx, kSmiTagSize); 1082 __ sar(ebx, kSmiTagSize);
1033 __ shl(ebx, shift_value); 1083 __ shl(ebx, shift_value);
1034 __ lea(ecx, Operand(ebx, 0x40000000)); 1084 __ lea(ecx, Operand(ebx, 0x40000000));
1035 __ test(ecx, Immediate(0x80000000)); 1085 __ test(ecx, Immediate(0x80000000));
1036 __ j(not_zero, deferred->enter(), not_taken); 1086 __ j(not_zero, deferred->enter(), not_taken);
1037 // tag result and store it in TOS (eax) 1087 // tag result and store it in TOS (eax)
1038 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1088 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
1039 __ lea(eax, Operand(ebx, times_2, kSmiTag)); 1089 __ lea(eax, Operand(ebx, times_2, kSmiTag));
1040 __ bind(deferred->exit()); 1090 __ bind(deferred->exit());
1041 __ push(eax); 1091 frame_->Push(eax);
1042 } 1092 }
1043 break; 1093 break;
1044 } 1094 }
1045 1095
1046 case Token::BIT_OR: 1096 case Token::BIT_OR:
1047 case Token::BIT_XOR: 1097 case Token::BIT_XOR:
1048 case Token::BIT_AND: { 1098 case Token::BIT_AND: {
1049 DeferredCode* deferred = NULL; 1099 DeferredCode* deferred = NULL;
1050 if (!reversed) { 1100 if (!reversed) {
1051 deferred = new DeferredInlinedSmiOperation(this, op, int_value, 1101 deferred = new DeferredInlinedSmiOperation(this, op, int_value,
1052 overwrite_mode); 1102 overwrite_mode);
1053 } else { 1103 } else {
1054 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value, 1104 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value,
1055 overwrite_mode); 1105 overwrite_mode);
1056 } 1106 }
1057 __ pop(eax); 1107 frame_->Pop(eax);
1058 __ test(eax, Immediate(kSmiTagMask)); 1108 __ test(eax, Immediate(kSmiTagMask));
1059 __ j(not_zero, deferred->enter(), not_taken); 1109 __ j(not_zero, deferred->enter(), not_taken);
1060 if (op == Token::BIT_AND) { 1110 if (op == Token::BIT_AND) {
1061 __ and_(Operand(eax), Immediate(value)); 1111 __ and_(Operand(eax), Immediate(value));
1062 } else if (op == Token::BIT_XOR) { 1112 } else if (op == Token::BIT_XOR) {
1063 __ xor_(Operand(eax), Immediate(value)); 1113 __ xor_(Operand(eax), Immediate(value));
1064 } else { 1114 } else {
1065 ASSERT(op == Token::BIT_OR); 1115 ASSERT(op == Token::BIT_OR);
1066 __ or_(Operand(eax), Immediate(value)); 1116 __ or_(Operand(eax), Immediate(value));
1067 } 1117 }
1068 __ bind(deferred->exit()); 1118 __ bind(deferred->exit());
1069 __ push(eax); 1119 frame_->Push(eax);
1070 break; 1120 break;
1071 } 1121 }
1072 1122
1073 default: { 1123 default: {
1074 if (!reversed) { 1124 if (!reversed) {
1075 __ push(Immediate(value)); 1125 frame_->Push(Immediate(value));
1076 } else { 1126 } else {
1077 __ pop(eax); 1127 frame_->Pop(eax);
1078 __ push(Immediate(value)); 1128 frame_->Push(Immediate(value));
1079 __ push(eax); 1129 frame_->Push(eax);
1080 } 1130 }
1081 GenericBinaryOperation(op, overwrite_mode); 1131 GenericBinaryOperation(op, overwrite_mode);
1082 break; 1132 break;
1083 } 1133 }
1084 } 1134 }
1085 } 1135 }
1086 1136
1087 1137
1088 class CompareStub: public CodeStub { 1138 class CompareStub: public CodeStub {
1089 public: 1139 public:
(...skipping 23 matching lines...) Expand all
1113 }; 1163 };
1114 1164
1115 1165
1116 void CodeGenerator::Comparison(Condition cc, bool strict) { 1166 void CodeGenerator::Comparison(Condition cc, bool strict) {
1117 // Strict only makes sense for equality comparisons. 1167 // Strict only makes sense for equality comparisons.
1118 ASSERT(!strict || cc == equal); 1168 ASSERT(!strict || cc == equal);
1119 1169
1120 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 1170 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
1121 if (cc == greater || cc == less_equal) { 1171 if (cc == greater || cc == less_equal) {
1122 cc = ReverseCondition(cc); 1172 cc = ReverseCondition(cc);
1123 __ pop(edx); 1173 frame_->Pop(edx);
1124 __ pop(eax); 1174 frame_->Pop(eax);
1125 } else { 1175 } else {
1126 __ pop(eax); 1176 frame_->Pop(eax);
1127 __ pop(edx); 1177 frame_->Pop(edx);
1128 } 1178 }
1129 1179
1130 // Check for the smi case. 1180 // Check for the smi case.
1131 Label is_smi, done; 1181 Label is_smi, done;
1132 __ mov(ecx, Operand(eax)); 1182 __ mov(ecx, Operand(eax));
1133 __ or_(ecx, Operand(edx)); 1183 __ or_(ecx, Operand(edx));
1134 __ test(ecx, Immediate(kSmiTagMask)); 1184 __ test(ecx, Immediate(kSmiTagMask));
1135 __ j(zero, &is_smi, taken); 1185 __ j(zero, &is_smi, taken);
1136 1186
1137 // When non-smi, call out to the compare stub. "parameters" setup by 1187 // When non-smi, call out to the compare stub. "parameters" setup by
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1188 Handle<Object> value, 1238 Handle<Object> value,
1189 bool strict) { 1239 bool strict) {
1190 // Strict only makes sense for equality comparisons. 1240 // Strict only makes sense for equality comparisons.
1191 ASSERT(!strict || cc == equal); 1241 ASSERT(!strict || cc == equal);
1192 1242
1193 int int_value = Smi::cast(*value)->value(); 1243 int int_value = Smi::cast(*value)->value();
1194 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); 1244 ASSERT(is_intn(int_value, kMaxSmiInlinedBits));
1195 1245
1196 SmiComparisonDeferred* deferred = 1246 SmiComparisonDeferred* deferred =
1197 new SmiComparisonDeferred(this, cc, strict, int_value); 1247 new SmiComparisonDeferred(this, cc, strict, int_value);
1198 __ pop(eax); 1248 frame_->Pop(eax);
1199 __ test(eax, Immediate(kSmiTagMask)); 1249 __ test(eax, Immediate(kSmiTagMask));
1200 __ j(not_zero, deferred->enter(), not_taken); 1250 __ j(not_zero, deferred->enter(), not_taken);
1201 // Test smi equality by pointer comparison. 1251 // Test smi equality by pointer comparison.
1202 __ cmp(Operand(eax), Immediate(value)); 1252 __ cmp(Operand(eax), Immediate(value));
1203 __ bind(deferred->exit()); 1253 __ bind(deferred->exit());
1204 cc_reg_ = cc; 1254 cc_reg_ = cc;
1205 } 1255 }
1206 1256
1207 1257
1208 class CallFunctionStub: public CodeStub { 1258 class CallFunctionStub: public CodeStub {
(...skipping 24 matching lines...) Expand all
1233 } 1283 }
1234 1284
1235 // Record the position for debugging purposes. 1285 // Record the position for debugging purposes.
1236 __ RecordPosition(position); 1286 __ RecordPosition(position);
1237 1287
1238 // Use the shared code stub to call the function. 1288 // Use the shared code stub to call the function.
1239 CallFunctionStub call_function(args->length()); 1289 CallFunctionStub call_function(args->length());
1240 __ CallStub(&call_function); 1290 __ CallStub(&call_function);
1241 1291
1242 // Restore context and pop function from the stack. 1292 // Restore context and pop function from the stack.
1243 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1293 __ mov(esi, frame_->Context());
1244 __ mov(TOS, eax); 1294 __ mov(frame_->Top(), eax);
1245 } 1295 }
1246 1296
1247 1297
1248 void CodeGenerator::Branch(bool if_true, Label* L) { 1298 void CodeGenerator::Branch(bool if_true, Label* L) {
1249 ASSERT(has_cc()); 1299 ASSERT(has_cc());
1250 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); 1300 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_);
1251 __ j(cc, L); 1301 __ j(cc, L);
1252 cc_reg_ = no_condition; 1302 cc_reg_ = no_condition;
1253 } 1303 }
1254 1304
(...skipping 15 matching lines...) Expand all
1270 void CodeGenerator::VisitBlock(Block* node) { 1320 void CodeGenerator::VisitBlock(Block* node) {
1271 Comment cmnt(masm_, "[ Block"); 1321 Comment cmnt(masm_, "[ Block");
1272 RecordStatementPosition(node); 1322 RecordStatementPosition(node);
1273 node->set_break_stack_height(break_stack_height_); 1323 node->set_break_stack_height(break_stack_height_);
1274 VisitStatements(node->statements()); 1324 VisitStatements(node->statements());
1275 __ bind(node->break_target()); 1325 __ bind(node->break_target());
1276 } 1326 }
1277 1327
1278 1328
1279 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1329 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1280 __ push(Immediate(pairs)); 1330 frame_->Push(Immediate(pairs));
1281 __ push(Operand(esi)); 1331 frame_->Push(esi);
1282 __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 1332 frame_->Push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
1283 __ CallRuntime(Runtime::kDeclareGlobals, 3); 1333 __ CallRuntime(Runtime::kDeclareGlobals, 3);
1284 // Return value is ignored. 1334 // Return value is ignored.
1285 } 1335 }
1286 1336
1287 1337
1288 void CodeGenerator::VisitDeclaration(Declaration* node) { 1338 void CodeGenerator::VisitDeclaration(Declaration* node) {
1289 Comment cmnt(masm_, "[ Declaration"); 1339 Comment cmnt(masm_, "[ Declaration");
1290 Variable* var = node->proxy()->var(); 1340 Variable* var = node->proxy()->var();
1291 ASSERT(var != NULL); // must have been resolved 1341 ASSERT(var != NULL); // must have been resolved
1292 Slot* slot = var->slot(); 1342 Slot* slot = var->slot();
1293 1343
1294 // If it was not possible to allocate the variable at compile time, 1344 // If it was not possible to allocate the variable at compile time,
1295 // we need to "declare" it at runtime to make sure it actually 1345 // we need to "declare" it at runtime to make sure it actually
1296 // exists in the local context. 1346 // exists in the local context.
1297 if (slot != NULL && slot->type() == Slot::LOOKUP) { 1347 if (slot != NULL && slot->type() == Slot::LOOKUP) {
1298 // Variables with a "LOOKUP" slot were introduced as non-locals 1348 // Variables with a "LOOKUP" slot were introduced as non-locals
1299 // during variable resolution and must have mode DYNAMIC. 1349 // during variable resolution and must have mode DYNAMIC.
1300 ASSERT(var->mode() == Variable::DYNAMIC); 1350 ASSERT(var->mode() == Variable::DYNAMIC);
1301 // For now, just do a runtime call. 1351 // For now, just do a runtime call.
1302 __ push(Operand(esi)); 1352 frame_->Push(esi);
1303 __ push(Immediate(var->name())); 1353 frame_->Push(Immediate(var->name()));
1304 // Declaration nodes are always introduced in one of two modes. 1354 // Declaration nodes are always introduced in one of two modes.
1305 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); 1355 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
1306 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; 1356 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
1307 __ push(Immediate(Smi::FromInt(attr))); 1357 frame_->Push(Immediate(Smi::FromInt(attr)));
1308 // Push initial value, if any. 1358 // Push initial value, if any.
1309 // Note: For variables we must not push an initial value (such as 1359 // Note: For variables we must not push an initial value (such as
1310 // 'undefined') because we may have a (legal) redeclaration and we 1360 // 'undefined') because we may have a (legal) redeclaration and we
1311 // must not destroy the current value. 1361 // must not destroy the current value.
1312 if (node->mode() == Variable::CONST) { 1362 if (node->mode() == Variable::CONST) {
1313 __ push(Immediate(Factory::the_hole_value())); 1363 frame_->Push(Immediate(Factory::the_hole_value()));
1314 } else if (node->fun() != NULL) { 1364 } else if (node->fun() != NULL) {
1315 Load(node->fun()); 1365 Load(node->fun());
1316 } else { 1366 } else {
1317 __ push(Immediate(0)); // no initial value! 1367 frame_->Push(Immediate(0)); // no initial value!
1318 } 1368 }
1319 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 1369 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
1320 // Ignore the return value (declarations are statements). 1370 // Ignore the return value (declarations are statements).
1321 return; 1371 return;
1322 } 1372 }
1323 1373
1324 ASSERT(!var->is_global()); 1374 ASSERT(!var->is_global());
1325 1375
1326 // If we have a function or a constant, we need to initialize the variable. 1376 // If we have a function or a constant, we need to initialize the variable.
1327 Expression* val = NULL; 1377 Expression* val = NULL;
1328 if (node->mode() == Variable::CONST) { 1378 if (node->mode() == Variable::CONST) {
1329 val = new Literal(Factory::the_hole_value()); 1379 val = new Literal(Factory::the_hole_value());
1330 } else { 1380 } else {
1331 val = node->fun(); // NULL if we don't have a function 1381 val = node->fun(); // NULL if we don't have a function
1332 } 1382 }
1333 1383
1334 if (val != NULL) { 1384 if (val != NULL) {
1335 // Set initial value. 1385 // Set initial value.
1336 Reference target(this, node->proxy()); 1386 Reference target(this, node->proxy());
1337 ASSERT(target.is_slot()); 1387 ASSERT(target.is_slot());
1338 Load(val); 1388 Load(val);
1339 target.SetValue(NOT_CONST_INIT); 1389 target.SetValue(NOT_CONST_INIT);
1340 // Get rid of the assigned value (declarations are statements). It's 1390 // Get rid of the assigned value (declarations are statements). It's
1341 // safe to pop the value lying on top of the reference before unloading 1391 // safe to pop the value lying on top of the reference before unloading
1342 // the reference itself (which preserves the top of stack) because we 1392 // the reference itself (which preserves the top of stack) because we
1343 // know that it is a zero-sized reference. 1393 // know that it is a zero-sized reference.
1344 __ pop(eax); // Pop(no_reg); 1394 frame_->Pop(eax); // Pop(no_reg);
iposva 2008/10/10 12:53:02 Another potential use of Pop()...
1345 } 1395 }
1346 } 1396 }
1347 1397
1348 1398
1349 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { 1399 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
1350 Comment cmnt(masm_, "[ ExpressionStatement"); 1400 Comment cmnt(masm_, "[ ExpressionStatement");
1351 RecordStatementPosition(node); 1401 RecordStatementPosition(node);
1352 Expression* expression = node->expression(); 1402 Expression* expression = node->expression();
1353 expression->MarkAsStatement(); 1403 expression->MarkAsStatement();
1354 Load(expression); 1404 Load(expression);
1355 __ pop(eax); // remove the lingering expression result from the top of stack 1405 frame_->Pop(eax); // remove the lingering expression result from the top of s tack
iposva 2008/10/10 12:53:02 And another potential use of Pop()...
1356 } 1406 }
1357 1407
1358 1408
1359 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { 1409 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
1360 Comment cmnt(masm_, "// EmptyStatement"); 1410 Comment cmnt(masm_, "// EmptyStatement");
1361 // nothing to do 1411 // nothing to do
1362 } 1412 }
1363 1413
1364 1414
1365 void CodeGenerator::VisitIfStatement(IfStatement* node) { 1415 void CodeGenerator::VisitIfStatement(IfStatement* node) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1407 1457
1408 } else { 1458 } else {
1409 ASSERT(!has_then_stm && !has_else_stm); 1459 ASSERT(!has_then_stm && !has_else_stm);
1410 // if (cond) 1460 // if (cond)
1411 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false); 1461 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false);
1412 if (has_cc()) { 1462 if (has_cc()) {
1413 cc_reg_ = no_condition; 1463 cc_reg_ = no_condition;
1414 } else { 1464 } else {
1415 // No cc value set up, that means the boolean was pushed. 1465 // No cc value set up, that means the boolean was pushed.
1416 // Pop it again, since it is not going to be used. 1466 // Pop it again, since it is not going to be used.
1417 __ pop(eax); 1467 frame_->Pop(eax);
1418 } 1468 }
1419 } 1469 }
1420 1470
1421 // end 1471 // end
1422 __ bind(&exit); 1472 __ bind(&exit);
1423 } 1473 }
1424 1474
1425 1475
1426 void CodeGenerator::CleanStack(int num_bytes) { 1476 void CodeGenerator::CleanStack(int num_bytes) {
1427 ASSERT(num_bytes >= 0); 1477 ASSERT(num_bytes % kPointerSize == 0);
1428 if (num_bytes > 0) { 1478 frame_->Drop(num_bytes / kPointerSize);
1429 __ add(Operand(esp), Immediate(num_bytes));
1430 }
1431 } 1479 }
1432 1480
1433 1481
1434 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { 1482 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
1435 Comment cmnt(masm_, "[ ContinueStatement"); 1483 Comment cmnt(masm_, "[ ContinueStatement");
1436 RecordStatementPosition(node); 1484 RecordStatementPosition(node);
1437 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1485 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1438 __ jmp(node->target()->continue_target()); 1486 __ jmp(node->target()->continue_target());
1439 } 1487 }
1440 1488
1441 1489
1442 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { 1490 void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
1443 Comment cmnt(masm_, "[ BreakStatement"); 1491 Comment cmnt(masm_, "[ BreakStatement");
1444 RecordStatementPosition(node); 1492 RecordStatementPosition(node);
1445 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1493 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1446 __ jmp(node->target()->break_target()); 1494 __ jmp(node->target()->break_target());
1447 } 1495 }
1448 1496
1449 1497
1450 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { 1498 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
1451 Comment cmnt(masm_, "[ ReturnStatement"); 1499 Comment cmnt(masm_, "[ ReturnStatement");
1452 RecordStatementPosition(node); 1500 RecordStatementPosition(node);
1453 Load(node->expression()); 1501 Load(node->expression());
1454 1502
1455 // Move the function result into eax 1503 // Move the function result into eax
1456 __ pop(eax); 1504 frame_->Pop(eax);
1457 1505
1458 // If we're inside a try statement or the return instruction 1506 // If we're inside a try statement or the return instruction
1459 // sequence has been generated, we just jump to that 1507 // sequence has been generated, we just jump to that
1460 // point. Otherwise, we generate the return instruction sequence and 1508 // point. Otherwise, we generate the return instruction sequence and
1461 // bind the function return label. 1509 // bind the function return label.
1462 if (is_inside_try_ || function_return_.is_bound()) { 1510 if (is_inside_try_ || function_return_.is_bound()) {
1463 __ jmp(&function_return_); 1511 __ jmp(&function_return_);
1464 } else { 1512 } else {
1465 __ bind(&function_return_); 1513 __ bind(&function_return_);
1466 if (FLAG_trace) { 1514 if (FLAG_trace) {
1467 __ push(eax); // undo the pop(eax) from above 1515 frame_->Push(eax); // undo the pop(eax) from above
1468 __ CallRuntime(Runtime::kTraceExit, 1); 1516 __ CallRuntime(Runtime::kTraceExit, 1);
1469 } 1517 }
1470 1518
1471 // Add a label for checking the size of the code used for returning. 1519 // Add a label for checking the size of the code used for returning.
1472 Label check_exit_codesize; 1520 Label check_exit_codesize;
1473 __ bind(&check_exit_codesize); 1521 __ bind(&check_exit_codesize);
1474 1522
1475 // Leave the frame and return popping the arguments and the 1523 // Leave the frame and return popping the arguments and the
1476 // receiver. 1524 // receiver.
1477 ExitJSFrame(); 1525 frame_->Exit();
1478 __ ret((scope_->num_parameters() + 1) * kPointerSize); 1526 __ ret((scope_->num_parameters() + 1) * kPointerSize);
1479 1527
1480 // Check that the size of the code used for returning matches what is 1528 // Check that the size of the code used for returning matches what is
1481 // expected by the debugger. 1529 // expected by the debugger.
1482 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, 1530 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
1483 __ SizeOfCodeGeneratedSince(&check_exit_codesize)); 1531 __ SizeOfCodeGeneratedSince(&check_exit_codesize));
1484 } 1532 }
1485 } 1533 }
1486 1534
1487 1535
1488 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 1536 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
1489 Comment cmnt(masm_, "[ WithEnterStatement"); 1537 Comment cmnt(masm_, "[ WithEnterStatement");
1490 RecordStatementPosition(node); 1538 RecordStatementPosition(node);
1491 Load(node->expression()); 1539 Load(node->expression());
1492 __ CallRuntime(Runtime::kPushContext, 1); 1540 __ CallRuntime(Runtime::kPushContext, 1);
1493 1541
1494 if (kDebug) { 1542 if (kDebug) {
1495 Label verified_true; 1543 Label verified_true;
1496 // Verify eax and esi are the same in debug mode 1544 // Verify eax and esi are the same in debug mode
1497 __ cmp(eax, Operand(esi)); 1545 __ cmp(eax, Operand(esi));
1498 __ j(equal, &verified_true); 1546 __ j(equal, &verified_true);
1499 __ int3(); 1547 __ int3();
1500 __ bind(&verified_true); 1548 __ bind(&verified_true);
1501 } 1549 }
1502 1550
1503 // Update context local. 1551 // Update context local.
1504 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 1552 __ mov(frame_->Context(), esi);
1505 } 1553 }
1506 1554
1507 1555
1508 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { 1556 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
1509 Comment cmnt(masm_, "[ WithExitStatement"); 1557 Comment cmnt(masm_, "[ WithExitStatement");
1510 // Pop context. 1558 // Pop context.
1511 __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX)); 1559 __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX));
1512 // Update context local. 1560 // Update context local.
1513 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 1561 __ mov(frame_->Context(), esi);
1514 } 1562 }
1515 1563
1516 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { 1564 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() {
1517 return kFastSwitchMaxOverheadFactor; 1565 return kFastSwitchMaxOverheadFactor;
1518 } 1566 }
1519 1567
1520 int CodeGenerator::FastCaseSwitchMinCaseCount() { 1568 int CodeGenerator::FastCaseSwitchMinCaseCount() {
1521 return kFastSwitchMinCaseCount; 1569 return kFastSwitchMinCaseCount;
1522 } 1570 }
1523 1571
1524 // Generate a computed jump to a switch case. 1572 // Generate a computed jump to a switch case.
1525 void CodeGenerator::GenerateFastCaseSwitchJumpTable( 1573 void CodeGenerator::GenerateFastCaseSwitchJumpTable(
1526 SwitchStatement* node, int min_index, int range, Label *fail_label, 1574 SwitchStatement* node, int min_index, int range, Label *fail_label,
1527 SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels) { 1575 SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels) {
1528 // Notice: Internal references, used by both the jmp instruction and 1576 // Notice: Internal references, used by both the jmp instruction and
1529 // the table entries, need to be relocated if the buffer grows. This 1577 // the table entries, need to be relocated if the buffer grows. This
1530 // prevents the forward use of Labels, since a displacement cannot 1578 // prevents the forward use of Labels, since a displacement cannot
1531 // survive relocation, and it also cannot safely be distinguished 1579 // survive relocation, and it also cannot safely be distinguished
1532 // from a real address. Instead we put in zero-values as 1580 // from a real address. Instead we put in zero-values as
1533 // placeholders, and fill in the addresses after the labels have been 1581 // placeholders, and fill in the addresses after the labels have been
1534 // bound. 1582 // bound.
1535 1583
1536 __ pop(eax); // supposed smi 1584 frame_->Pop(eax); // supposed smi
1537 // check range of value, if outside [0..length-1] jump to default/end label. 1585 // check range of value, if outside [0..length-1] jump to default/end label.
1538 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 1586 ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1539 if (min_index != 0) { 1587 if (min_index != 0) {
1540 __ sub(Operand(eax), Immediate(min_index << kSmiTagSize)); 1588 __ sub(Operand(eax), Immediate(min_index << kSmiTagSize));
1541 } 1589 }
1542 __ test(eax, Immediate(0x80000000 | kSmiTagMask)); // negative or not Smi 1590 __ test(eax, Immediate(0x80000000 | kSmiTagMask)); // negative or not Smi
1543 __ j(not_equal, fail_label, not_taken); 1591 __ j(not_equal, fail_label, not_taken);
1544 __ cmp(eax, range << kSmiTagSize); 1592 __ cmp(eax, range << kSmiTagSize);
1545 __ j(greater_equal, fail_label, not_taken); 1593 __ j(greater_equal, fail_label, not_taken);
1546 1594
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1592 // statements if it does not match any of the cases. 1640 // statements if it does not match any of the cases.
1593 __ jmp(&next); 1641 __ jmp(&next);
1594 1642
1595 // Bind the default case label, so we can branch to it when we 1643 // Bind the default case label, so we can branch to it when we
1596 // have compared against all other cases. 1644 // have compared against all other cases.
1597 ASSERT(default_case.is_unused()); // at most one default clause 1645 ASSERT(default_case.is_unused()); // at most one default clause
1598 __ bind(&default_case); 1646 __ bind(&default_case);
1599 } else { 1647 } else {
1600 __ bind(&next); 1648 __ bind(&next);
1601 next.Unuse(); 1649 next.Unuse();
1602 __ mov(eax, TOS); 1650 __ mov(eax, frame_->Top());
1603 __ push(eax); // duplicate TOS 1651 frame_->Push(eax); // duplicate TOS
1604 Load(clause->label()); 1652 Load(clause->label());
1605 Comparison(equal, true); 1653 Comparison(equal, true);
1606 Branch(false, &next); 1654 Branch(false, &next);
1607 } 1655 }
1608 1656
1609 // Entering the case statement for the first time. Remove the switch value 1657 // Entering the case statement for the first time. Remove the switch value
1610 // from the stack. 1658 // from the stack.
1611 __ pop(eax); 1659 frame_->Pop(eax);
1612 1660
1613 // Generate code for the body. 1661 // Generate code for the body.
1614 // This is also the target for the fall through from the previous case's 1662 // This is also the target for the fall through from the previous case's
1615 // statements which has to skip over the matching code and the popping of 1663 // statements which has to skip over the matching code and the popping of
1616 // the switch value. 1664 // the switch value.
1617 __ bind(&fall_through); 1665 __ bind(&fall_through);
1618 fall_through.Unuse(); 1666 fall_through.Unuse();
1619 VisitStatements(clause->statements()); 1667 VisitStatements(clause->statements());
1620 __ jmp(&fall_through); 1668 __ jmp(&fall_through);
1621 } 1669 }
1622 1670
1623 __ bind(&next); 1671 __ bind(&next);
1624 // Reached the end of the case statements without matching any of the cases. 1672 // Reached the end of the case statements without matching any of the cases.
1625 if (default_case.is_bound()) { 1673 if (default_case.is_bound()) {
1626 // A default case exists -> execute its statements. 1674 // A default case exists -> execute its statements.
1627 __ jmp(&default_case); 1675 __ jmp(&default_case);
1628 } else { 1676 } else {
1629 // Remove the switch value from the stack. 1677 // Remove the switch value from the stack.
1630 __ pop(eax); 1678 frame_->Pop(eax);
1631 } 1679 }
1632 1680
1633 __ bind(&fall_through); 1681 __ bind(&fall_through);
1634 __ bind(node->break_target()); 1682 __ bind(node->break_target());
1635 } 1683 }
1636 1684
1637 1685
1638 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 1686 void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
1639 Comment cmnt(masm_, "[ LoopStatement"); 1687 Comment cmnt(masm_, "[ LoopStatement");
1640 RecordStatementPosition(node); 1688 RecordStatementPosition(node);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1716 node->set_break_stack_height(break_stack_height_); 1764 node->set_break_stack_height(break_stack_height_);
1717 1765
1718 Label loop, next, entry, cleanup, exit, primitive, jsobject; 1766 Label loop, next, entry, cleanup, exit, primitive, jsobject;
1719 Label end_del_check, fixed_array; 1767 Label end_del_check, fixed_array;
1720 1768
1721 // Get the object to enumerate over (converted to JSObject). 1769 // Get the object to enumerate over (converted to JSObject).
1722 Load(node->enumerable()); 1770 Load(node->enumerable());
1723 1771
1724 // Both SpiderMonkey and kjs ignore null and undefined in contrast 1772 // Both SpiderMonkey and kjs ignore null and undefined in contrast
1725 // to the specification. 12.6.4 mandates a call to ToObject. 1773 // to the specification. 12.6.4 mandates a call to ToObject.
1726 __ pop(eax); 1774 frame_->Pop(eax);
1727 1775
1728 // eax: value to be iterated over 1776 // eax: value to be iterated over
1729 __ cmp(eax, Factory::undefined_value()); 1777 __ cmp(eax, Factory::undefined_value());
1730 __ j(equal, &exit); 1778 __ j(equal, &exit);
1731 __ cmp(eax, Factory::null_value()); 1779 __ cmp(eax, Factory::null_value());
1732 __ j(equal, &exit); 1780 __ j(equal, &exit);
1733 1781
1734 // Stack layout in body: 1782 // Stack layout in body:
1735 // [iteration counter (smi)] <- slot 0 1783 // [iteration counter (smi)] <- slot 0
1736 // [length of array] <- slot 1 1784 // [length of array] <- slot 1
1737 // [FixedArray] <- slot 2 1785 // [FixedArray] <- slot 2
1738 // [Map or 0] <- slot 3 1786 // [Map or 0] <- slot 3
1739 // [Object] <- slot 4 1787 // [Object] <- slot 4
1740 1788
1741 // Check if enumerable is already a JSObject 1789 // Check if enumerable is already a JSObject
1742 // eax: value to be iterated over 1790 // eax: value to be iterated over
1743 __ test(eax, Immediate(kSmiTagMask)); 1791 __ test(eax, Immediate(kSmiTagMask));
1744 __ j(zero, &primitive); 1792 __ j(zero, &primitive);
1745 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 1793 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
1746 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 1794 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
1747 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 1795 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
1748 __ j(above_equal, &jsobject); 1796 __ j(above_equal, &jsobject);
1749 1797
1750 __ bind(&primitive); 1798 __ bind(&primitive);
1751 __ push(eax); 1799 frame_->Push(eax);
1752 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1800 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1753 // function call returns the value in eax, which is where we want it below 1801 // function call returns the value in eax, which is where we want it below
1754 1802
1755 1803
1756 __ bind(&jsobject); 1804 __ bind(&jsobject);
1757 1805
1758 // Get the set of properties (as a FixedArray or Map). 1806 // Get the set of properties (as a FixedArray or Map).
1759 // eax: value to be iterated over 1807 // eax: value to be iterated over
1760 __ push(eax); // push the object being iterated over (slot 4) 1808 frame_->Push(eax); // push the object being iterated over (slot 4)
1761 1809
1762 __ push(eax); // push the Object (slot 4) for the runtime call 1810 frame_->Push(eax); // push the Object (slot 4) for the runtime call
1763 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1811 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1764 1812
1765 // If we got a Map, we can do a fast modification check. 1813 // If we got a Map, we can do a fast modification check.
1766 // Otherwise, we got a FixedArray, and we have to do a slow check. 1814 // Otherwise, we got a FixedArray, and we have to do a slow check.
1767 // eax: map or fixed array (result from call to 1815 // eax: map or fixed array (result from call to
1768 // Runtime::kGetPropertyNamesFast) 1816 // Runtime::kGetPropertyNamesFast)
1769 __ mov(edx, Operand(eax)); 1817 __ mov(edx, Operand(eax));
1770 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 1818 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
1771 __ cmp(ecx, Factory::meta_map()); 1819 __ cmp(ecx, Factory::meta_map());
1772 __ j(not_equal, &fixed_array); 1820 __ j(not_equal, &fixed_array);
1773 1821
1774 // Get enum cache 1822 // Get enum cache
1775 // eax: map (result from call to Runtime::kGetPropertyNamesFast) 1823 // eax: map (result from call to Runtime::kGetPropertyNamesFast)
1776 __ mov(ecx, Operand(eax)); 1824 __ mov(ecx, Operand(eax));
1777 __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset)); 1825 __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset));
1778 // Get the bridge array held in the enumeration index field. 1826 // Get the bridge array held in the enumeration index field.
1779 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); 1827 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
1780 // Get the cache from the bridge array. 1828 // Get the cache from the bridge array.
1781 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1829 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1782 1830
1783 __ push(eax); // <- slot 3 1831 frame_->Push(eax); // <- slot 3
1784 __ push(Operand(edx)); // <- slot 2 1832 frame_->Push(edx); // <- slot 2
1785 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); 1833 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
1786 __ shl(eax, kSmiTagSize); 1834 __ shl(eax, kSmiTagSize);
1787 __ push(eax); // <- slot 1 1835 frame_->Push(eax); // <- slot 1
1788 __ push(Immediate(Smi::FromInt(0))); // <- slot 0 1836 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0
1789 __ jmp(&entry); 1837 __ jmp(&entry);
1790 1838
1791 1839
1792 __ bind(&fixed_array); 1840 __ bind(&fixed_array);
1793 1841
1794 // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast) 1842 // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast)
1795 __ push(Immediate(Smi::FromInt(0))); // <- slot 3 1843 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 3
1796 __ push(eax); // <- slot 2 1844 frame_->Push(eax); // <- slot 2
1797 1845
1798 // Push the length of the array and the initial index onto the stack. 1846 // Push the length of the array and the initial index onto the stack.
1799 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); 1847 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
1800 __ shl(eax, kSmiTagSize); 1848 __ shl(eax, kSmiTagSize);
1801 __ push(eax); // <- slot 1 1849 frame_->Push(eax); // <- slot 1
1802 __ push(Immediate(Smi::FromInt(0))); // <- slot 0 1850 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0
1803 __ jmp(&entry); 1851 __ jmp(&entry);
1804 1852
1805 // Body. 1853 // Body.
1806 __ bind(&loop); 1854 __ bind(&loop);
1807 Visit(node->body()); 1855 Visit(node->body());
1808 1856
1809 // Next. 1857 // Next.
1810 __ bind(node->continue_target()); 1858 __ bind(node->continue_target());
1811 __ bind(&next); 1859 __ bind(&next);
1812 __ pop(eax); 1860 frame_->Pop(eax);
1813 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 1861 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
1814 __ push(eax); 1862 frame_->Push(eax);
1815 1863
1816 // Condition. 1864 // Condition.
1817 __ bind(&entry); 1865 __ bind(&entry);
1818 1866
1819 __ mov(eax, Operand(esp, 0 * kPointerSize)); // load the current count 1867 __ mov(eax, frame_->Element(0)); // load the current count
1820 __ cmp(eax, Operand(esp, kPointerSize)); // compare to the array length 1868 __ cmp(eax, frame_->Element(1)); // compare to the array length
1821 __ j(above_equal, &cleanup); 1869 __ j(above_equal, &cleanup);
1822 1870
1823 // Get the i'th entry of the array. 1871 // Get the i'th entry of the array.
1824 __ mov(edx, Operand(esp, 2 * kPointerSize)); 1872 __ mov(edx, frame_->Element(2));
1825 __ mov(ebx, Operand(edx, eax, times_2, 1873 __ mov(ebx, Operand(edx, eax, times_2,
1826 FixedArray::kHeaderSize - kHeapObjectTag)); 1874 FixedArray::kHeaderSize - kHeapObjectTag));
1827 1875
1828 // Get the expected map from the stack or a zero map in the 1876 // Get the expected map from the stack or a zero map in the
1829 // permanent slow case eax: current iteration count ebx: i'th entry 1877 // permanent slow case eax: current iteration count ebx: i'th entry
1830 // of the enum cache 1878 // of the enum cache
1831 __ mov(edx, Operand(esp, 3 * kPointerSize)); 1879 __ mov(edx, frame_->Element(3));
1832 // Check if the expected map still matches that of the enumerable. 1880 // Check if the expected map still matches that of the enumerable.
1833 // If not, we have to filter the key. 1881 // If not, we have to filter the key.
1834 // eax: current iteration count 1882 // eax: current iteration count
1835 // ebx: i'th entry of the enum cache 1883 // ebx: i'th entry of the enum cache
1836 // edx: expected map value 1884 // edx: expected map value
1837 __ mov(ecx, Operand(esp, 4 * kPointerSize)); 1885 __ mov(ecx, frame_->Element(4));
1838 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); 1886 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
1839 __ cmp(ecx, Operand(edx)); 1887 __ cmp(ecx, Operand(edx));
1840 __ j(equal, &end_del_check); 1888 __ j(equal, &end_del_check);
1841 1889
1842 // Convert the entry to a string (or null if it isn't a property anymore). 1890 // Convert the entry to a string (or null if it isn't a property anymore).
1843 __ push(Operand(esp, 4 * kPointerSize)); // push enumerable 1891 frame_->Push(frame_->Element(4)); // push enumerable
1844 __ push(Operand(ebx)); // push entry 1892 frame_->Push(ebx); // push entry
1845 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1893 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1846 __ mov(ebx, Operand(eax)); 1894 __ mov(ebx, Operand(eax));
1847 1895
1848 // If the property has been removed while iterating, we just skip it. 1896 // If the property has been removed while iterating, we just skip it.
1849 __ cmp(ebx, Factory::null_value()); 1897 __ cmp(ebx, Factory::null_value());
1850 __ j(equal, &next); 1898 __ j(equal, &next);
1851 1899
1852 1900
1853 __ bind(&end_del_check); 1901 __ bind(&end_del_check);
1854 1902
1855 // Store the entry in the 'each' expression and take another spin in the loop. 1903 // Store the entry in the 'each' expression and take another spin in the loop.
1856 // edx: i'th entry of the enum cache (or string there of) 1904 // edx: i'th entry of the enum cache (or string there of)
1857 __ push(ebx); 1905 frame_->Push(ebx);
1858 { Reference each(this, node->each()); 1906 { Reference each(this, node->each());
1859 if (!each.is_illegal()) { 1907 if (!each.is_illegal()) {
1860 if (each.size() > 0) { 1908 if (each.size() > 0) {
1861 __ push(Operand(esp, kPointerSize * each.size())); 1909 frame_->Push(frame_->Element(each.size()));
1862 } 1910 }
1863 // If the reference was to a slot we rely on the convenient property 1911 // If the reference was to a slot we rely on the convenient property
1864 // that it doesn't matter whether a value (eg, ebx pushed above) is 1912 // that it doesn't matter whether a value (eg, ebx pushed above) is
1865 // right on top of or right underneath a zero-sized reference. 1913 // right on top of or right underneath a zero-sized reference.
1866 each.SetValue(NOT_CONST_INIT); 1914 each.SetValue(NOT_CONST_INIT);
1867 if (each.size() > 0) { 1915 if (each.size() > 0) {
1868 // It's safe to pop the value lying on top of the reference before 1916 // It's safe to pop the value lying on top of the reference before
1869 // unloading the reference itself (which preserves the top of stack, 1917 // unloading the reference itself (which preserves the top of stack,
1870 // ie, now the topmost value of the non-zero sized reference), since 1918 // ie, now the topmost value of the non-zero sized reference), since
1871 // we will discard the top of stack after unloading the reference 1919 // we will discard the top of stack after unloading the reference
1872 // anyway. 1920 // anyway.
1873 __ pop(eax); 1921 frame_->Pop(eax);
1874 } 1922 }
1875 } 1923 }
1876 } 1924 }
1877 // Discard the i'th entry pushed above or else the remainder of the 1925 // Discard the i'th entry pushed above or else the remainder of the
1878 // reference, whichever is currently on top of the stack. 1926 // reference, whichever is currently on top of the stack.
1879 __ pop(eax); 1927 frame_->Pop(eax);
1880 CheckStack(); // TODO(1222600): ignore if body contains calls. 1928 CheckStack(); // TODO(1222600): ignore if body contains calls.
1881 __ jmp(&loop); 1929 __ jmp(&loop);
1882 1930
1883 // Cleanup. 1931 // Cleanup.
1884 __ bind(&cleanup); 1932 __ bind(&cleanup);
1885 __ bind(node->break_target()); 1933 __ bind(node->break_target());
1886 __ add(Operand(esp), Immediate(5 * kPointerSize)); 1934 frame_->Drop(5);
1887 1935
1888 // Exit. 1936 // Exit.
1889 __ bind(&exit); 1937 __ bind(&exit);
1890 1938
1891 break_stack_height_ -= kForInStackSize; 1939 break_stack_height_ -= kForInStackSize;
1892 } 1940 }
1893 1941
1894 1942
1895 void CodeGenerator::VisitTryCatch(TryCatch* node) { 1943 void CodeGenerator::VisitTryCatch(TryCatch* node) {
1896 Comment cmnt(masm_, "[ TryCatch"); 1944 Comment cmnt(masm_, "[ TryCatch");
1897 1945
1898 Label try_block, exit; 1946 Label try_block, exit;
1899 1947
1900 __ call(&try_block); 1948 __ call(&try_block);
1901 // --- Catch block --- 1949 // --- Catch block ---
1902 __ push(eax); 1950 frame_->Push(eax);
1903 1951
1904 // Store the caught exception in the catch variable. 1952 // Store the caught exception in the catch variable.
1905 { Reference ref(this, node->catch_var()); 1953 { Reference ref(this, node->catch_var());
1906 ASSERT(ref.is_slot()); 1954 ASSERT(ref.is_slot());
1907 // Load the exception to the top of the stack. Here we make use of the 1955 // Load the exception to the top of the stack. Here we make use of the
1908 // convenient property that it doesn't matter whether a value is 1956 // convenient property that it doesn't matter whether a value is
1909 // immediately on top of or underneath a zero-sized reference. 1957 // immediately on top of or underneath a zero-sized reference.
1910 ref.SetValue(NOT_CONST_INIT); 1958 ref.SetValue(NOT_CONST_INIT);
1911 } 1959 }
1912 1960
1913 // Remove the exception from the stack. 1961 // Remove the exception from the stack.
1914 __ pop(edx); 1962 frame_->Pop(edx);
1915 1963
1916 VisitStatements(node->catch_block()->statements()); 1964 VisitStatements(node->catch_block()->statements());
1917 __ jmp(&exit); 1965 __ jmp(&exit);
1918 1966
1919 1967
1920 // --- Try block --- 1968 // --- Try block ---
1921 __ bind(&try_block); 1969 __ bind(&try_block);
1922 1970
1923 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); 1971 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
1924 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS 1972 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS
1925 __ push(eax); // 1973 frame_->Push(eax); //
1926 1974
1927 // Introduce shadow labels for all escapes from the try block, 1975 // Introduce shadow labels for all escapes from the try block,
1928 // including returns. We should probably try to unify the escaping 1976 // including returns. We should probably try to unify the escaping
1929 // labels and the return label. 1977 // labels and the return label.
1930 int nof_escapes = node->escaping_labels()->length(); 1978 int nof_escapes = node->escaping_labels()->length();
1931 List<LabelShadow*> shadows(1 + nof_escapes); 1979 List<LabelShadow*> shadows(1 + nof_escapes);
1932 shadows.Add(new LabelShadow(&function_return_)); 1980 shadows.Add(new LabelShadow(&function_return_));
1933 for (int i = 0; i < nof_escapes; i++) { 1981 for (int i = 0; i < nof_escapes; i++) {
1934 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); 1982 shadows.Add(new LabelShadow(node->escaping_labels()->at(i)));
1935 } 1983 }
(...skipping 17 matching lines...) Expand all
1953 // Make sure that there's nothing left on the stack above the 2001 // Make sure that there's nothing left on the stack above the
1954 // handler structure. 2002 // handler structure.
1955 if (FLAG_debug_code) { 2003 if (FLAG_debug_code) {
1956 __ mov(eax, Operand::StaticVariable(handler_address)); 2004 __ mov(eax, Operand::StaticVariable(handler_address));
1957 __ lea(eax, Operand(eax, StackHandlerConstants::kAddressDisplacement)); 2005 __ lea(eax, Operand(eax, StackHandlerConstants::kAddressDisplacement));
1958 __ cmp(esp, Operand(eax)); 2006 __ cmp(esp, Operand(eax));
1959 __ Assert(equal, "stack pointer should point to top handler"); 2007 __ Assert(equal, "stack pointer should point to top handler");
1960 } 2008 }
1961 2009
1962 // Unlink from try chain. 2010 // Unlink from try chain.
1963 __ pop(eax); 2011 frame_->Pop(eax);
1964 __ mov(Operand::StaticVariable(handler_address), eax); // TOS == next_sp 2012 __ mov(Operand::StaticVariable(handler_address), eax); // TOS == next_sp
1965 __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); 2013 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
1966 // next_sp popped. 2014 // next_sp popped.
1967 if (nof_unlinks > 0) __ jmp(&exit); 2015 if (nof_unlinks > 0) __ jmp(&exit);
1968 2016
1969 // Generate unlink code for all used shadow labels. 2017 // Generate unlink code for all used shadow labels.
1970 for (int i = 0; i <= nof_escapes; i++) { 2018 for (int i = 0; i <= nof_escapes; i++) {
1971 if (shadows[i]->is_linked()) { 2019 if (shadows[i]->is_linked()) {
1972 // Unlink from try chain; be careful not to destroy the TOS. 2020 // Unlink from try chain; be careful not to destroy the TOS.
1973 __ bind(shadows[i]); 2021 __ bind(shadows[i]);
1974 2022
1975 // Reload sp from the top handler, because some statements that we 2023 // Reload sp from the top handler, because some statements that we
1976 // break from (eg, for...in) may have left stuff on the stack. 2024 // break from (eg, for...in) may have left stuff on the stack.
1977 __ mov(edx, Operand::StaticVariable(handler_address)); 2025 __ mov(edx, Operand::StaticVariable(handler_address));
1978 const int kNextOffset = StackHandlerConstants::kNextOffset + 2026 const int kNextOffset = StackHandlerConstants::kNextOffset +
1979 StackHandlerConstants::kAddressDisplacement; 2027 StackHandlerConstants::kAddressDisplacement;
1980 __ lea(esp, Operand(edx, kNextOffset)); 2028 __ lea(esp, Operand(edx, kNextOffset));
1981 2029
1982 __ pop(Operand::StaticVariable(handler_address)); 2030 frame_->Pop(Operand::StaticVariable(handler_address));
1983 __ add(Operand(esp), 2031 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
1984 Immediate(StackHandlerConstants::kSize - kPointerSize));
1985 // next_sp popped. 2032 // next_sp popped.
1986 __ jmp(shadows[i]->shadowed()); 2033 __ jmp(shadows[i]->shadowed());
1987 } 2034 }
1988 } 2035 }
1989 2036
1990 __ bind(&exit); 2037 __ bind(&exit);
1991 } 2038 }
1992 2039
1993 2040
1994 void CodeGenerator::VisitTryFinally(TryFinally* node) { 2041 void CodeGenerator::VisitTryFinally(TryFinally* node) {
1995 Comment cmnt(masm_, "[ TryFinally"); 2042 Comment cmnt(masm_, "[ TryFinally");
1996 2043
1997 // State: Used to keep track of reason for entering the finally 2044 // State: Used to keep track of reason for entering the finally
1998 // block. Should probably be extended to hold information for 2045 // block. Should probably be extended to hold information for
1999 // break/continue from within the try block. 2046 // break/continue from within the try block.
2000 enum { FALLING, THROWING, JUMPING }; 2047 enum { FALLING, THROWING, JUMPING };
2001 2048
2002 Label exit, unlink, try_block, finally_block; 2049 Label exit, unlink, try_block, finally_block;
2003 2050
2004 __ call(&try_block); 2051 __ call(&try_block);
2005 2052
2006 __ push(eax); 2053 frame_->Push(eax);
2007 // In case of thrown exceptions, this is where we continue. 2054 // In case of thrown exceptions, this is where we continue.
2008 __ Set(ecx, Immediate(Smi::FromInt(THROWING))); 2055 __ Set(ecx, Immediate(Smi::FromInt(THROWING)));
2009 __ jmp(&finally_block); 2056 __ jmp(&finally_block);
2010 2057
2011 2058
2012 // --- Try block --- 2059 // --- Try block ---
2013 __ bind(&try_block); 2060 __ bind(&try_block);
2014 2061
2015 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); 2062 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
2016 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS 2063 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS
2017 __ push(eax); 2064 frame_->Push(eax);
2018 2065
2019 // Introduce shadow labels for all escapes from the try block, 2066 // Introduce shadow labels for all escapes from the try block,
2020 // including returns. We should probably try to unify the escaping 2067 // including returns. We should probably try to unify the escaping
2021 // labels and the return label. 2068 // labels and the return label.
2022 int nof_escapes = node->escaping_labels()->length(); 2069 int nof_escapes = node->escaping_labels()->length();
2023 List<LabelShadow*> shadows(1 + nof_escapes); 2070 List<LabelShadow*> shadows(1 + nof_escapes);
2024 shadows.Add(new LabelShadow(&function_return_)); 2071 shadows.Add(new LabelShadow(&function_return_));
2025 for (int i = 0; i < nof_escapes; i++) { 2072 for (int i = 0; i < nof_escapes; i++) {
2026 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); 2073 shadows.Add(new LabelShadow(node->escaping_labels()->at(i)));
2027 } 2074 }
2028 2075
2029 // Generate code for the statements in the try block. 2076 // Generate code for the statements in the try block.
2030 bool was_inside_try = is_inside_try_; 2077 bool was_inside_try = is_inside_try_;
2031 is_inside_try_ = true; 2078 is_inside_try_ = true;
2032 VisitStatements(node->try_block()->statements()); 2079 VisitStatements(node->try_block()->statements());
2033 is_inside_try_ = was_inside_try; 2080 is_inside_try_ = was_inside_try;
2034 2081
2035 // Stop the introduced shadowing and count the number of required 2082 // Stop the introduced shadowing and count the number of required
2036 // unlinks. 2083 // unlinks.
2037 int nof_unlinks = 0; 2084 int nof_unlinks = 0;
2038 for (int i = 0; i <= nof_escapes; i++) { 2085 for (int i = 0; i <= nof_escapes; i++) {
2039 shadows[i]->StopShadowing(); 2086 shadows[i]->StopShadowing();
2040 if (shadows[i]->is_linked()) nof_unlinks++; 2087 if (shadows[i]->is_linked()) nof_unlinks++;
2041 } 2088 }
2042 2089
2043 // Set the state on the stack to FALLING. 2090 // Set the state on the stack to FALLING.
2044 __ push(Immediate(Factory::undefined_value())); // fake TOS 2091 frame_->Push(Immediate(Factory::undefined_value())); // fake TOS
2045 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); 2092 __ Set(ecx, Immediate(Smi::FromInt(FALLING)));
2046 if (nof_unlinks > 0) __ jmp(&unlink); 2093 if (nof_unlinks > 0) __ jmp(&unlink);
2047 2094
2048 // Generate code that sets the state for all used shadow labels. 2095 // Generate code that sets the state for all used shadow labels.
2049 for (int i = 0; i <= nof_escapes; i++) { 2096 for (int i = 0; i <= nof_escapes; i++) {
2050 if (shadows[i]->is_linked()) { 2097 if (shadows[i]->is_linked()) {
2051 __ bind(shadows[i]); 2098 __ bind(shadows[i]);
2052 if (shadows[i]->shadowed() == &function_return_) { 2099 if (shadows[i]->shadowed() == &function_return_) {
2053 // Materialize the return value on the stack. 2100 // Materialize the return value on the stack.
2054 __ push(eax); 2101 frame_->Push(eax);
2055 } else { 2102 } else {
2056 // Fake TOS for break and continue. 2103 // Fake TOS for break and continue.
2057 __ push(Immediate(Factory::undefined_value())); 2104 frame_->Push(Immediate(Factory::undefined_value()));
2058 } 2105 }
2059 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i))); 2106 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i)));
2060 __ jmp(&unlink); 2107 __ jmp(&unlink);
2061 } 2108 }
2062 } 2109 }
2063 2110
2064 // Unlink from try chain; be careful not to destroy the TOS. 2111 // Unlink from try chain; be careful not to destroy the TOS.
2065 __ bind(&unlink); 2112 __ bind(&unlink);
2066 // Reload sp from the top handler, because some statements that we 2113 // Reload sp from the top handler, because some statements that we
2067 // break from (eg, for...in) may have left stuff on the stack. 2114 // break from (eg, for...in) may have left stuff on the stack.
2068 __ pop(eax); // preserve the TOS in a register across stack manipulation 2115 frame_->Pop(eax); // preserve the TOS in a register across stack manipulation
2069 ExternalReference handler_address(Top::k_handler_address); 2116 ExternalReference handler_address(Top::k_handler_address);
2070 __ mov(edx, Operand::StaticVariable(handler_address)); 2117 __ mov(edx, Operand::StaticVariable(handler_address));
2071 const int kNextOffset = StackHandlerConstants::kNextOffset + 2118 const int kNextOffset = StackHandlerConstants::kNextOffset +
2072 StackHandlerConstants::kAddressDisplacement; 2119 StackHandlerConstants::kAddressDisplacement;
2073 __ lea(esp, Operand(edx, kNextOffset)); 2120 __ lea(esp, Operand(edx, kNextOffset));
2074 2121
2075 __ pop(Operand::StaticVariable(handler_address)); 2122 frame_->Pop(Operand::StaticVariable(handler_address));
2076 __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); 2123 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2077 // next_sp popped. 2124 // next_sp popped.
2078 __ push(eax); // preserve the TOS in a register across stack manipulation 2125 frame_->Push(eax); // preserve the TOS in a register across stack manipulatio n
2079 2126
2080 // --- Finally block --- 2127 // --- Finally block ---
2081 __ bind(&finally_block); 2128 __ bind(&finally_block);
2082 2129
2083 // Push the state on the stack. 2130 // Push the state on the stack.
2084 __ push(ecx); 2131 frame_->Push(ecx);
2085 2132
2086 // We keep two elements on the stack - the (possibly faked) result 2133 // We keep two elements on the stack - the (possibly faked) result
2087 // and the state - while evaluating the finally block. Record it, so 2134 // and the state - while evaluating the finally block. Record it, so
2088 // that a break/continue crossing this statement can restore the 2135 // that a break/continue crossing this statement can restore the
2089 // stack. 2136 // stack.
2090 const int kFinallyStackSize = 2 * kPointerSize; 2137 const int kFinallyStackSize = 2 * kPointerSize;
2091 break_stack_height_ += kFinallyStackSize; 2138 break_stack_height_ += kFinallyStackSize;
2092 2139
2093 // Generate code for the statements in the finally block. 2140 // Generate code for the statements in the finally block.
2094 VisitStatements(node->finally_block()->statements()); 2141 VisitStatements(node->finally_block()->statements());
2095 2142
2096 // Restore state and return value or faked TOS. 2143 // Restore state and return value or faked TOS.
2097 __ pop(ecx); 2144 frame_->Pop(ecx);
2098 __ pop(eax); 2145 frame_->Pop(eax);
2099 break_stack_height_ -= kFinallyStackSize; 2146 break_stack_height_ -= kFinallyStackSize;
2100 2147
2101 // Generate code that jumps to the right destination for all used 2148 // Generate code that jumps to the right destination for all used
2102 // shadow labels. 2149 // shadow labels.
2103 for (int i = 0; i <= nof_escapes; i++) { 2150 for (int i = 0; i <= nof_escapes; i++) {
2104 if (shadows[i]->is_bound()) { 2151 if (shadows[i]->is_bound()) {
2105 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); 2152 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i)));
2106 __ j(equal, shadows[i]->shadowed()); 2153 __ j(equal, shadows[i]->shadowed());
2107 } 2154 }
2108 } 2155 }
2109 2156
2110 // Check if we need to rethrow the exception. 2157 // Check if we need to rethrow the exception.
2111 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING))); 2158 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING)));
2112 __ j(not_equal, &exit); 2159 __ j(not_equal, &exit);
2113 2160
2114 // Rethrow exception. 2161 // Rethrow exception.
2115 __ push(eax); // undo pop from above 2162 frame_->Push(eax); // undo pop from above
2116 __ CallRuntime(Runtime::kReThrow, 1); 2163 __ CallRuntime(Runtime::kReThrow, 1);
2117 2164
2118 // Done. 2165 // Done.
2119 __ bind(&exit); 2166 __ bind(&exit);
2120 } 2167 }
2121 2168
2122 2169
2123 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { 2170 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
2124 Comment cmnt(masm_, "[ DebuggerStatement"); 2171 Comment cmnt(masm_, "[ DebuggerStatement");
2125 RecordStatementPosition(node); 2172 RecordStatementPosition(node);
2126 __ CallRuntime(Runtime::kDebugBreak, 1); 2173 __ CallRuntime(Runtime::kDebugBreak, 1);
2127 __ push(eax); 2174 frame_->Push(eax);
2128 } 2175 }
2129 2176
2130 2177
2131 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { 2178 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
2132 ASSERT(boilerplate->IsBoilerplate()); 2179 ASSERT(boilerplate->IsBoilerplate());
2133 2180
2134 // Push the boilerplate on the stack. 2181 // Push the boilerplate on the stack.
2135 __ push(Immediate(boilerplate)); 2182 frame_->Push(Immediate(boilerplate));
2136 2183
2137 // Create a new closure. 2184 // Create a new closure.
2138 __ push(esi); 2185 frame_->Push(esi);
2139 __ CallRuntime(Runtime::kNewClosure, 2); 2186 __ CallRuntime(Runtime::kNewClosure, 2);
2140 __ push(eax); 2187 frame_->Push(eax);
2141 } 2188 }
2142 2189
2143 2190
2144 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 2191 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
2145 Comment cmnt(masm_, "[ FunctionLiteral"); 2192 Comment cmnt(masm_, "[ FunctionLiteral");
2146 2193
2147 // Build the function boilerplate and instantiate it. 2194 // Build the function boilerplate and instantiate it.
2148 Handle<JSFunction> boilerplate = BuildBoilerplate(node); 2195 Handle<JSFunction> boilerplate = BuildBoilerplate(node);
2149 // Check for stack-overflow exception. 2196 // Check for stack-overflow exception.
2150 if (HasStackOverflow()) return; 2197 if (HasStackOverflow()) return;
(...skipping 20 matching lines...) Expand all
2171 Load(node->else_expression(), typeof_state()); 2218 Load(node->else_expression(), typeof_state());
2172 __ bind(&exit); 2219 __ bind(&exit);
2173 } 2220 }
2174 2221
2175 2222
2176 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2223 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2177 if (slot->type() == Slot::LOOKUP) { 2224 if (slot->type() == Slot::LOOKUP) {
2178 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2225 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2179 2226
2180 // For now, just do a runtime call. 2227 // For now, just do a runtime call.
2181 __ push(esi); 2228 frame_->Push(esi);
2182 __ push(Immediate(slot->var()->name())); 2229 frame_->Push(Immediate(slot->var()->name()));
2183 2230
2184 if (typeof_state == INSIDE_TYPEOF) { 2231 if (typeof_state == INSIDE_TYPEOF) {
2185 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2232 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2186 } else { 2233 } else {
2187 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2234 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2188 } 2235 }
2189 __ push(eax); 2236 frame_->Push(eax);
2190 2237
2191 } else { 2238 } else {
2192 // Note: We would like to keep the assert below, but it fires because of 2239 // Note: We would like to keep the assert below, but it fires because of
2193 // some nasty code in LoadTypeofExpression() which should be removed... 2240 // some nasty code in LoadTypeofExpression() which should be removed...
2194 // ASSERT(slot->var()->mode() != Variable::DYNAMIC); 2241 // ASSERT(slot->var()->mode() != Variable::DYNAMIC);
2195 if (slot->var()->mode() == Variable::CONST) { 2242 if (slot->var()->mode() == Variable::CONST) {
2196 // Const slots may contain 'the hole' value (the constant hasn't been 2243 // Const slots may contain 'the hole' value (the constant hasn't been
2197 // initialized yet) which needs to be converted into the 'undefined' 2244 // initialized yet) which needs to be converted into the 'undefined'
2198 // value. 2245 // value.
2199 Comment cmnt(masm_, "[ Load const"); 2246 Comment cmnt(masm_, "[ Load const");
2200 Label exit; 2247 Label exit;
2201 __ mov(eax, SlotOperand(slot, ecx)); 2248 __ mov(eax, SlotOperand(slot, ecx));
2202 __ cmp(eax, Factory::the_hole_value()); 2249 __ cmp(eax, Factory::the_hole_value());
2203 __ j(not_equal, &exit); 2250 __ j(not_equal, &exit);
2204 __ mov(eax, Factory::undefined_value()); 2251 __ mov(eax, Factory::undefined_value());
2205 __ bind(&exit); 2252 __ bind(&exit);
2206 __ push(eax); 2253 frame_->Push(eax);
2207 } else { 2254 } else {
2208 __ push(SlotOperand(slot, ecx)); 2255 frame_->Push(SlotOperand(slot, ecx));
2209 } 2256 }
2210 } 2257 }
2211 } 2258 }
2212 2259
2213 2260
2214 void CodeGenerator::VisitSlot(Slot* node) { 2261 void CodeGenerator::VisitSlot(Slot* node) {
2215 Comment cmnt(masm_, "[ Slot"); 2262 Comment cmnt(masm_, "[ Slot");
2216 LoadFromSlot(node, typeof_state()); 2263 LoadFromSlot(node, typeof_state());
2217 } 2264 }
2218 2265
(...skipping 13 matching lines...) Expand all
2232 2279
2233 2280
2234 void CodeGenerator::VisitLiteral(Literal* node) { 2281 void CodeGenerator::VisitLiteral(Literal* node) {
2235 Comment cmnt(masm_, "[ Literal"); 2282 Comment cmnt(masm_, "[ Literal");
2236 if (node->handle()->IsSmi() && !IsInlineSmi(node)) { 2283 if (node->handle()->IsSmi() && !IsInlineSmi(node)) {
2237 // To prevent long attacker-controlled byte sequences in code, larger 2284 // To prevent long attacker-controlled byte sequences in code, larger
2238 // Smis are loaded in two steps. 2285 // Smis are loaded in two steps.
2239 int bits = reinterpret_cast<int>(*node->handle()); 2286 int bits = reinterpret_cast<int>(*node->handle());
2240 __ mov(eax, bits & 0x0000FFFF); 2287 __ mov(eax, bits & 0x0000FFFF);
2241 __ xor_(eax, bits & 0xFFFF0000); 2288 __ xor_(eax, bits & 0xFFFF0000);
2242 __ push(eax); 2289 frame_->Push(eax);
2243 } else { 2290 } else {
2244 __ push(Immediate(node->handle())); 2291 frame_->Push(Immediate(node->handle()));
2245 } 2292 }
2246 } 2293 }
2247 2294
2248 2295
2249 class RegExpDeferred: public DeferredCode { 2296 class RegExpDeferred: public DeferredCode {
2250 public: 2297 public:
2251 RegExpDeferred(CodeGenerator* generator, RegExpLiteral* node) 2298 RegExpDeferred(CodeGenerator* generator, RegExpLiteral* node)
2252 : DeferredCode(generator), node_(node) { 2299 : DeferredCode(generator), node_(node) {
2253 set_comment("[ RegExpDeferred"); 2300 set_comment("[ RegExpDeferred");
2254 } 2301 }
(...skipping 20 matching lines...) Expand all
2275 } 2322 }
2276 2323
2277 2324
2278 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 2325 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
2279 Comment cmnt(masm_, "[ RegExp Literal"); 2326 Comment cmnt(masm_, "[ RegExp Literal");
2280 RegExpDeferred* deferred = new RegExpDeferred(this, node); 2327 RegExpDeferred* deferred = new RegExpDeferred(this, node);
2281 2328
2282 // Retrieve the literal array and check the allocated entry. 2329 // Retrieve the literal array and check the allocated entry.
2283 2330
2284 // Load the function of this activation. 2331 // Load the function of this activation.
2285 __ mov(ecx, FunctionOperand()); 2332 __ mov(ecx, frame_->Function());
2286 2333
2287 // Load the literals array of the function. 2334 // Load the literals array of the function.
2288 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2335 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
2289 2336
2290 // Load the literal at the ast saved index. 2337 // Load the literal at the ast saved index.
2291 int literal_offset = 2338 int literal_offset =
2292 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 2339 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
2293 __ mov(ebx, FieldOperand(ecx, literal_offset)); 2340 __ mov(ebx, FieldOperand(ecx, literal_offset));
2294 2341
2295 // Check whether we need to materialize the RegExp object. 2342 // Check whether we need to materialize the RegExp object.
2296 // If so, jump to the deferred code. 2343 // If so, jump to the deferred code.
2297 __ cmp(ebx, Factory::undefined_value()); 2344 __ cmp(ebx, Factory::undefined_value());
2298 __ j(equal, deferred->enter(), not_taken); 2345 __ j(equal, deferred->enter(), not_taken);
2299 __ bind(deferred->exit()); 2346 __ bind(deferred->exit());
2300 2347
2301 // Push the literal. 2348 // Push the literal.
2302 __ push(ebx); 2349 frame_->Push(ebx);
2303 } 2350 }
2304 2351
2305 2352
2306 // This deferred code stub will be used for creating the boilerplate 2353 // This deferred code stub will be used for creating the boilerplate
2307 // by calling Runtime_CreateObjectLiteral. 2354 // by calling Runtime_CreateObjectLiteral.
2308 // Each created boilerplate is stored in the JSFunction and they are 2355 // Each created boilerplate is stored in the JSFunction and they are
2309 // therefore context dependent. 2356 // therefore context dependent.
2310 class ObjectLiteralDeferred: public DeferredCode { 2357 class ObjectLiteralDeferred: public DeferredCode {
2311 public: 2358 public:
2312 ObjectLiteralDeferred(CodeGenerator* generator, 2359 ObjectLiteralDeferred(CodeGenerator* generator,
2313 ObjectLiteral* node) 2360 ObjectLiteral* node)
2314 : DeferredCode(generator), node_(node) { 2361 : DeferredCode(generator), node_(node) {
2315 set_comment("[ ObjectLiteralDeferred"); 2362 set_comment("[ ObjectLiteralDeferred");
2316 } 2363 }
2317 virtual void Generate(); 2364 virtual void Generate();
2318 private: 2365 private:
2319 ObjectLiteral* node_; 2366 ObjectLiteral* node_;
2320 }; 2367 };
2321 2368
2322 2369
2323 void ObjectLiteralDeferred::Generate() { 2370 void ObjectLiteralDeferred::Generate() {
2324 // If the entry is undefined we call the runtime system to compute 2371 // If the entry is undefined we call the runtime system to compute
2325 // the literal. 2372 // the literal.
2326 2373
2327 // Literal array (0). 2374 // Literal array (0).
2328 __ push(Operand(ecx)); 2375 __ push(ecx);
2329 // Literal index (1). 2376 // Literal index (1).
2330 __ push(Immediate(Smi::FromInt(node_->literal_index()))); 2377 __ push(Immediate(Smi::FromInt(node_->literal_index())));
2331 // Constant properties (2). 2378 // Constant properties (2).
2332 __ push(Immediate(node_->constant_properties())); 2379 __ push(Immediate(node_->constant_properties()));
2333 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); 2380 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
2334 __ mov(ebx, Operand(eax)); 2381 __ mov(ebx, Operand(eax));
2335 } 2382 }
2336 2383
2337 2384
2338 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 2385 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
2339 Comment cmnt(masm_, "[ ObjectLiteral"); 2386 Comment cmnt(masm_, "[ ObjectLiteral");
2340 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); 2387 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);
2341 2388
2342 // Retrieve the literal array and check the allocated entry. 2389 // Retrieve the literal array and check the allocated entry.
2343 2390
2344 // Load the function of this activation. 2391 // Load the function of this activation.
2345 __ mov(ecx, FunctionOperand()); 2392 __ mov(ecx, frame_->Function());
2346 2393
2347 // Load the literals array of the function. 2394 // Load the literals array of the function.
2348 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2395 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
2349 2396
2350 // Load the literal at the ast saved index. 2397 // Load the literal at the ast saved index.
2351 int literal_offset = 2398 int literal_offset =
2352 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 2399 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
2353 __ mov(ebx, FieldOperand(ecx, literal_offset)); 2400 __ mov(ebx, FieldOperand(ecx, literal_offset));
2354 2401
2355 // Check whether we need to materialize the object literal boilerplate. 2402 // Check whether we need to materialize the object literal boilerplate.
2356 // If so, jump to the deferred code. 2403 // If so, jump to the deferred code.
2357 __ cmp(ebx, Factory::undefined_value()); 2404 __ cmp(ebx, Factory::undefined_value());
2358 __ j(equal, deferred->enter(), not_taken); 2405 __ j(equal, deferred->enter(), not_taken);
2359 __ bind(deferred->exit()); 2406 __ bind(deferred->exit());
2360 2407
2361 // Push the literal. 2408 // Push the literal.
2362 __ push(ebx); 2409 frame_->Push(ebx);
2363 // Clone the boilerplate object. 2410 // Clone the boilerplate object.
2364 __ CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); 2411 __ CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1);
2365 // Push the new cloned literal object as the result. 2412 // Push the new cloned literal object as the result.
2366 __ push(eax); 2413 frame_->Push(eax);
2367 2414
2368 2415
2369 for (int i = 0; i < node->properties()->length(); i++) { 2416 for (int i = 0; i < node->properties()->length(); i++) {
2370 ObjectLiteral::Property* property = node->properties()->at(i); 2417 ObjectLiteral::Property* property = node->properties()->at(i);
2371 switch (property->kind()) { 2418 switch (property->kind()) {
2372 case ObjectLiteral::Property::CONSTANT: break; 2419 case ObjectLiteral::Property::CONSTANT: break;
2373 case ObjectLiteral::Property::COMPUTED: { 2420 case ObjectLiteral::Property::COMPUTED: {
2374 Handle<Object> key(property->key()->handle()); 2421 Handle<Object> key(property->key()->handle());
2375 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2422 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
2376 if (key->IsSymbol()) { 2423 if (key->IsSymbol()) {
2377 __ mov(eax, TOS); 2424 __ mov(eax, frame_->Top());
2378 __ push(eax); 2425 frame_->Push(eax);
2379 Load(property->value()); 2426 Load(property->value());
2380 __ pop(eax); 2427 frame_->Pop(eax);
2381 __ Set(ecx, Immediate(key)); 2428 __ Set(ecx, Immediate(key));
2382 __ call(ic, RelocInfo::CODE_TARGET); 2429 __ call(ic, RelocInfo::CODE_TARGET);
2383 __ add(Operand(esp), Immediate(kPointerSize)); 2430 frame_->Drop(1);
2384 // Ignore result. 2431 // Ignore result.
2385 break; 2432 break;
2386 } 2433 }
2387 // Fall through 2434 // Fall through
2388 } 2435 }
2389 case ObjectLiteral::Property::PROTOTYPE: { 2436 case ObjectLiteral::Property::PROTOTYPE: {
2390 __ mov(eax, TOS); 2437 __ mov(eax, frame_->Top());
2391 __ push(eax); 2438 frame_->Push(eax);
2392 Load(property->key()); 2439 Load(property->key());
2393 Load(property->value()); 2440 Load(property->value());
2394 __ CallRuntime(Runtime::kSetProperty, 3); 2441 __ CallRuntime(Runtime::kSetProperty, 3);
2395 // Ignore result. 2442 // Ignore result.
2396 break; 2443 break;
2397 } 2444 }
2398 case ObjectLiteral::Property::SETTER: { 2445 case ObjectLiteral::Property::SETTER: {
2399 // Duplicate the resulting object on the stack. The runtime 2446 // Duplicate the resulting object on the stack. The runtime
2400 // function will pop the three arguments passed in. 2447 // function will pop the three arguments passed in.
2401 __ mov(eax, TOS); 2448 __ mov(eax, frame_->Top());
2402 __ push(eax); 2449 frame_->Push(eax);
2403 Load(property->key()); 2450 Load(property->key());
2404 __ push(Immediate(Smi::FromInt(1))); 2451 frame_->Push(Immediate(Smi::FromInt(1)));
2405 Load(property->value()); 2452 Load(property->value());
2406 __ CallRuntime(Runtime::kDefineAccessor, 4); 2453 __ CallRuntime(Runtime::kDefineAccessor, 4);
2407 // Ignore result. 2454 // Ignore result.
2408 break; 2455 break;
2409 } 2456 }
2410 case ObjectLiteral::Property::GETTER: { 2457 case ObjectLiteral::Property::GETTER: {
2411 // Duplicate the resulting object on the stack. The runtime 2458 // Duplicate the resulting object on the stack. The runtime
2412 // function will pop the three arguments passed in. 2459 // function will pop the three arguments passed in.
2413 __ mov(eax, TOS); 2460 __ mov(eax, frame_->Top());
2414 __ push(eax); 2461 frame_->Push(eax);
2415 Load(property->key()); 2462 Load(property->key());
2416 __ push(Immediate(Smi::FromInt(0))); 2463 frame_->Push(Immediate(Smi::FromInt(0)));
2417 Load(property->value()); 2464 Load(property->value());
2418 __ CallRuntime(Runtime::kDefineAccessor, 4); 2465 __ CallRuntime(Runtime::kDefineAccessor, 4);
2419 // Ignore result. 2466 // Ignore result.
2420 break; 2467 break;
2421 } 2468 }
2422 default: UNREACHABLE(); 2469 default: UNREACHABLE();
2423 } 2470 }
2424 } 2471 }
2425 } 2472 }
2426 2473
2427 2474
2428 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 2475 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
2429 Comment cmnt(masm_, "[ ArrayLiteral"); 2476 Comment cmnt(masm_, "[ ArrayLiteral");
2430 2477
2431 // Call runtime to create the array literal. 2478 // Call runtime to create the array literal.
2432 __ push(Immediate(node->literals())); 2479 frame_->Push(Immediate(node->literals()));
2433 // Load the function of this frame. 2480 // Load the function of this frame.
2434 __ mov(ecx, FunctionOperand()); 2481 __ mov(ecx, frame_->Function());
2435 // Load the literals array of the function. 2482 // Load the literals array of the function.
2436 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2483 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
2437 __ push(ecx); 2484 frame_->Push(ecx);
2438 __ CallRuntime(Runtime::kCreateArrayLiteral, 2); 2485 __ CallRuntime(Runtime::kCreateArrayLiteral, 2);
2439 2486
2440 // Push the resulting array literal on the stack. 2487 // Push the resulting array literal on the stack.
2441 __ push(eax); 2488 frame_->Push(eax);
2442 2489
2443 // Generate code to set the elements in the array that are not 2490 // Generate code to set the elements in the array that are not
2444 // literals. 2491 // literals.
2445 for (int i = 0; i < node->values()->length(); i++) { 2492 for (int i = 0; i < node->values()->length(); i++) {
2446 Expression* value = node->values()->at(i); 2493 Expression* value = node->values()->at(i);
2447 2494
2448 // If value is literal the property value is already 2495 // If value is literal the property value is already
2449 // set in the boilerplate object. 2496 // set in the boilerplate object.
2450 if (value->AsLiteral() == NULL) { 2497 if (value->AsLiteral() == NULL) {
2451 // The property must be set by generated code. 2498 // The property must be set by generated code.
2452 Load(value); 2499 Load(value);
2453 2500
2454 // Get the value off the stack. 2501 // Get the value off the stack.
2455 __ pop(eax); 2502 frame_->Pop(eax);
2456 // Fetch the object literal while leaving on the stack. 2503 // Fetch the object literal while leaving on the stack.
2457 __ mov(ecx, TOS); 2504 __ mov(ecx, frame_->Top());
2458 // Get the elements array. 2505 // Get the elements array.
2459 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); 2506 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
2460 2507
2461 // Write to the indexed properties array. 2508 // Write to the indexed properties array.
2462 int offset = i * kPointerSize + Array::kHeaderSize; 2509 int offset = i * kPointerSize + Array::kHeaderSize;
2463 __ mov(FieldOperand(ecx, offset), eax); 2510 __ mov(FieldOperand(ecx, offset), eax);
2464 2511
2465 // Update the write barrier for the array address. 2512 // Update the write barrier for the array address.
2466 __ RecordWrite(ecx, offset, eax, ebx); 2513 __ RecordWrite(ecx, offset, eax, ebx);
2467 } 2514 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2517 } 2564 }
2518 } 2565 }
2519 2566
2520 2567
2521 void CodeGenerator::VisitThrow(Throw* node) { 2568 void CodeGenerator::VisitThrow(Throw* node) {
2522 Comment cmnt(masm_, "[ Throw"); 2569 Comment cmnt(masm_, "[ Throw");
2523 2570
2524 Load(node->exception()); 2571 Load(node->exception());
2525 __ RecordPosition(node->position()); 2572 __ RecordPosition(node->position());
2526 __ CallRuntime(Runtime::kThrow, 1); 2573 __ CallRuntime(Runtime::kThrow, 1);
2527 __ push(eax); 2574 frame_->Push(eax);
2528 } 2575 }
2529 2576
2530 2577
2531 void CodeGenerator::VisitProperty(Property* node) { 2578 void CodeGenerator::VisitProperty(Property* node) {
2532 Comment cmnt(masm_, "[ Property"); 2579 Comment cmnt(masm_, "[ Property");
2533 2580
2534 Reference property(this, node); 2581 Reference property(this, node);
2535 property.GetValue(typeof_state()); 2582 property.GetValue(typeof_state());
2536 } 2583 }
2537 2584
(...skipping 18 matching lines...) Expand all
2556 // automatically handles this by loading the arguments before the function 2603 // automatically handles this by loading the arguments before the function
2557 // is resolved in cache misses (this also holds for megamorphic calls). 2604 // is resolved in cache misses (this also holds for megamorphic calls).
2558 // ------------------------------------------------------------------------ 2605 // ------------------------------------------------------------------------
2559 2606
2560 if (var != NULL && !var->is_this() && var->is_global()) { 2607 if (var != NULL && !var->is_this() && var->is_global()) {
2561 // ---------------------------------- 2608 // ----------------------------------
2562 // JavaScript example: 'foo(1, 2, 3)' // foo is global 2609 // JavaScript example: 'foo(1, 2, 3)' // foo is global
2563 // ---------------------------------- 2610 // ----------------------------------
2564 2611
2565 // Push the name of the function and the receiver onto the stack. 2612 // Push the name of the function and the receiver onto the stack.
2566 __ push(Immediate(var->name())); 2613 frame_->Push(Immediate(var->name()));
2567 LoadGlobal(); 2614 LoadGlobal();
2568 2615
2569 // Load the arguments. 2616 // Load the arguments.
2570 for (int i = 0; i < args->length(); i++) { 2617 for (int i = 0; i < args->length(); i++) {
2571 Load(args->at(i)); 2618 Load(args->at(i));
2572 } 2619 }
2573 2620
2574 // Setup the receiver register and call the IC initialization code. 2621 // Setup the receiver register and call the IC initialization code.
2575 Handle<Code> stub = ComputeCallInitialize(args->length()); 2622 Handle<Code> stub = ComputeCallInitialize(args->length());
2576 __ RecordPosition(node->position()); 2623 __ RecordPosition(node->position());
2577 __ call(stub, RelocInfo::CODE_TARGET_CONTEXT); 2624 __ call(stub, RelocInfo::CODE_TARGET_CONTEXT);
2578 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2625 __ mov(esi, frame_->Context());
2579 2626
2580 // Overwrite the function on the stack with the result. 2627 // Overwrite the function on the stack with the result.
2581 __ mov(TOS, eax); 2628 __ mov(frame_->Top(), eax);
2582 2629
2583 } else if (var != NULL && var->slot() != NULL && 2630 } else if (var != NULL && var->slot() != NULL &&
2584 var->slot()->type() == Slot::LOOKUP) { 2631 var->slot()->type() == Slot::LOOKUP) {
2585 // ---------------------------------- 2632 // ----------------------------------
2586 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj 2633 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj
2587 // ---------------------------------- 2634 // ----------------------------------
2588 2635
2589 // Load the function 2636 // Load the function
2590 __ push(Operand(esi)); 2637 frame_->Push(esi);
2591 __ push(Immediate(var->name())); 2638 frame_->Push(Immediate(var->name()));
2592 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2639 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2593 // eax: slot value; edx: receiver 2640 // eax: slot value; edx: receiver
2594 2641
2595 // Load the receiver. 2642 // Load the receiver.
2596 __ push(eax); 2643 frame_->Push(eax);
2597 __ push(edx); 2644 frame_->Push(edx);
2598 2645
2599 // Call the function. 2646 // Call the function.
2600 CallWithArguments(args, node->position()); 2647 CallWithArguments(args, node->position());
2601 2648
2602 } else if (property != NULL) { 2649 } else if (property != NULL) {
2603 // Check if the key is a literal string. 2650 // Check if the key is a literal string.
2604 Literal* literal = property->key()->AsLiteral(); 2651 Literal* literal = property->key()->AsLiteral();
2605 2652
2606 if (literal != NULL && literal->handle()->IsSymbol()) { 2653 if (literal != NULL && literal->handle()->IsSymbol()) {
2607 // ------------------------------------------------------------------ 2654 // ------------------------------------------------------------------
2608 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 2655 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
2609 // ------------------------------------------------------------------ 2656 // ------------------------------------------------------------------
2610 2657
2611 // Push the name of the function and the receiver onto the stack. 2658 // Push the name of the function and the receiver onto the stack.
2612 __ push(Immediate(literal->handle())); 2659 frame_->Push(Immediate(literal->handle()));
2613 Load(property->obj()); 2660 Load(property->obj());
2614 2661
2615 // Load the arguments. 2662 // Load the arguments.
2616 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 2663 for (int i = 0; i < args->length(); i++) Load(args->at(i));
2617 2664
2618 // Call the IC initialization code. 2665 // Call the IC initialization code.
2619 Handle<Code> stub = ComputeCallInitialize(args->length()); 2666 Handle<Code> stub = ComputeCallInitialize(args->length());
2620 __ RecordPosition(node->position()); 2667 __ RecordPosition(node->position());
2621 __ call(stub, RelocInfo::CODE_TARGET); 2668 __ call(stub, RelocInfo::CODE_TARGET);
2622 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2669 __ mov(esi, frame_->Context());
2623 2670
2624 // Overwrite the function on the stack with the result. 2671 // Overwrite the function on the stack with the result.
2625 __ mov(TOS, eax); 2672 __ mov(frame_->Top(), eax);
2626 2673
2627 } else { 2674 } else {
2628 // ------------------------------------------- 2675 // -------------------------------------------
2629 // JavaScript example: 'array[index](1, 2, 3)' 2676 // JavaScript example: 'array[index](1, 2, 3)'
2630 // ------------------------------------------- 2677 // -------------------------------------------
2631 2678
2632 // Load the function to call from the property through a reference. 2679 // Load the function to call from the property through a reference.
2633 Reference ref(this, property); 2680 Reference ref(this, property);
2634 ref.GetValue(NOT_INSIDE_TYPEOF); 2681 ref.GetValue(NOT_INSIDE_TYPEOF);
2635 2682
2636 // Pass receiver to called function. 2683 // Pass receiver to called function.
2637 // The reference's size is non-negative. 2684 // The reference's size is non-negative.
2638 __ push(Operand(esp, ref.size() * kPointerSize)); 2685 frame_->Push(frame_->Element(ref.size()));
2639 2686
2640 // Call the function. 2687 // Call the function.
2641 CallWithArguments(args, node->position()); 2688 CallWithArguments(args, node->position());
2642 } 2689 }
2643 2690
2644 } else { 2691 } else {
2645 // ---------------------------------- 2692 // ----------------------------------
2646 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 2693 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
2647 // ---------------------------------- 2694 // ----------------------------------
2648 2695
(...skipping 27 matching lines...) Expand all
2676 ZoneList<Expression*>* args = node->arguments(); 2723 ZoneList<Expression*>* args = node->arguments();
2677 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 2724 for (int i = 0; i < args->length(); i++) Load(args->at(i));
2678 2725
2679 // Constructors are called with the number of arguments in register 2726 // Constructors are called with the number of arguments in register
2680 // eax for now. Another option would be to have separate construct 2727 // eax for now. Another option would be to have separate construct
2681 // call trampolines per different arguments counts encountered. 2728 // call trampolines per different arguments counts encountered.
2682 __ Set(eax, Immediate(args->length())); 2729 __ Set(eax, Immediate(args->length()));
2683 2730
2684 // Load the function into temporary function slot as per calling 2731 // Load the function into temporary function slot as per calling
2685 // convention. 2732 // convention.
2686 __ mov(edi, Operand(esp, (args->length() + 1) * kPointerSize)); 2733 __ mov(edi, frame_->Element(args->length() + 1));
2687 2734
2688 // Call the construct call builtin that handles allocation and 2735 // Call the construct call builtin that handles allocation and
2689 // constructor invocation. 2736 // constructor invocation.
2690 __ RecordPosition(node->position()); 2737 __ RecordPosition(node->position());
2691 __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), 2738 __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
2692 RelocInfo::CONSTRUCT_CALL); 2739 RelocInfo::CONSTRUCT_CALL);
2693 __ mov(TOS, eax); // discard the function and "push" the newly created object 2740 // Discard the function and "push" the newly created object.
2741 __ mov(frame_->Top(), eax);
2694 } 2742 }
2695 2743
2696 2744
2697 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 2745 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
2698 ASSERT(args->length() == 1); 2746 ASSERT(args->length() == 1);
2699 Load(args->at(0)); 2747 Load(args->at(0));
2700 __ pop(eax); 2748 frame_->Pop(eax);
2701 __ test(eax, Immediate(kSmiTagMask)); 2749 __ test(eax, Immediate(kSmiTagMask));
2702 cc_reg_ = zero; 2750 cc_reg_ = zero;
2703 } 2751 }
2704 2752
2705 2753
2706 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 2754 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
2707 ASSERT(args->length() == 1); 2755 ASSERT(args->length() == 1);
2708 Load(args->at(0)); 2756 Load(args->at(0));
2709 __ pop(eax); 2757 frame_->Pop(eax);
2710 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 2758 __ test(eax, Immediate(kSmiTagMask | 0x80000000));
2711 cc_reg_ = zero; 2759 cc_reg_ = zero;
2712 } 2760 }
2713 2761
2714 2762
2715 // This generates code that performs a charCodeAt() call or returns 2763 // This generates code that performs a charCodeAt() call or returns
2716 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 2764 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
2717 // It can handle flat and sliced strings, 8 and 16 bit characters and 2765 // It can handle flat and sliced strings, 8 and 16 bit characters and
2718 // cons strings where the answer is found in the left hand branch of the 2766 // cons strings where the answer is found in the left hand branch of the
2719 // cons. The slow case will flatten the string, which will ensure that 2767 // cons. The slow case will flatten the string, which will ensure that
2720 // the answer is in the left hand side the next time around. 2768 // the answer is in the left hand side the next time around.
2721 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 2769 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
2722 ASSERT(args->length() == 2); 2770 ASSERT(args->length() == 2);
2723 2771
2724 Label slow_case; 2772 Label slow_case;
2725 Label end; 2773 Label end;
2726 Label not_a_flat_string; 2774 Label not_a_flat_string;
2727 Label not_a_cons_string_either; 2775 Label not_a_cons_string_either;
2728 Label try_again_with_new_string; 2776 Label try_again_with_new_string;
2729 Label ascii_string; 2777 Label ascii_string;
2730 Label got_char_code; 2778 Label got_char_code;
2731 2779
2732 // Load the string into eax. 2780 // Load the string into eax.
2733 Load(args->at(0)); 2781 Load(args->at(0));
2734 __ pop(eax); 2782 frame_->Pop(eax);
2735 // If the receiver is a smi return undefined. 2783 // If the receiver is a smi return undefined.
2736 ASSERT(kSmiTag == 0); 2784 ASSERT(kSmiTag == 0);
2737 __ test(eax, Immediate(kSmiTagMask)); 2785 __ test(eax, Immediate(kSmiTagMask));
2738 __ j(zero, &slow_case, not_taken); 2786 __ j(zero, &slow_case, not_taken);
2739 2787
2740 // Load the index into ebx. 2788 // Load the index into ebx.
2741 Load(args->at(1)); 2789 Load(args->at(1));
2742 __ pop(ebx); 2790 frame_->Pop(ebx);
2743 2791
2744 // Check for negative or non-smi index. 2792 // Check for negative or non-smi index.
2745 ASSERT(kSmiTag == 0); 2793 ASSERT(kSmiTag == 0);
2746 __ test(ebx, Immediate(kSmiTagMask | 0x80000000)); 2794 __ test(ebx, Immediate(kSmiTagMask | 0x80000000));
2747 __ j(not_zero, &slow_case, not_taken); 2795 __ j(not_zero, &slow_case, not_taken);
2748 // Get rid of the smi tag on the index. 2796 // Get rid of the smi tag on the index.
2749 __ sar(ebx, kSmiTagSize); 2797 __ sar(ebx, kSmiTagSize);
2750 2798
2751 __ bind(&try_again_with_new_string); 2799 __ bind(&try_again_with_new_string);
2752 // Get the type of the heap object into ecx. 2800 // Get the type of the heap object into ecx.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2803 __ jmp(&got_char_code); 2851 __ jmp(&got_char_code);
2804 2852
2805 // ASCII string. 2853 // ASCII string.
2806 __ bind(&ascii_string); 2854 __ bind(&ascii_string);
2807 // Load the byte. 2855 // Load the byte.
2808 __ movzx_b(eax, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); 2856 __ movzx_b(eax, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
2809 2857
2810 __ bind(&got_char_code); 2858 __ bind(&got_char_code);
2811 ASSERT(kSmiTag == 0); 2859 ASSERT(kSmiTag == 0);
2812 __ shl(eax, kSmiTagSize); 2860 __ shl(eax, kSmiTagSize);
2813 __ push(eax); 2861 frame_->Push(eax);
2814 __ jmp(&end); 2862 __ jmp(&end);
2815 2863
2816 2864
2817 // Handle non-flat strings. 2865 // Handle non-flat strings.
2818 __ bind(&not_a_flat_string); 2866 __ bind(&not_a_flat_string);
2819 __ and_(ecx, kStringRepresentationMask); 2867 __ and_(ecx, kStringRepresentationMask);
2820 __ cmp(ecx, kConsStringTag); 2868 __ cmp(ecx, kConsStringTag);
2821 __ j(not_equal, &not_a_cons_string_either, not_taken); 2869 __ j(not_equal, &not_a_cons_string_either, not_taken);
2822 2870
2823 // ConsString. 2871 // ConsString.
2824 // Get the first of the two strings. 2872 // Get the first of the two strings.
2825 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); 2873 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
2826 __ jmp(&try_again_with_new_string); 2874 __ jmp(&try_again_with_new_string);
2827 2875
2828 __ bind(&not_a_cons_string_either); 2876 __ bind(&not_a_cons_string_either);
2829 __ cmp(ecx, kSlicedStringTag); 2877 __ cmp(ecx, kSlicedStringTag);
2830 __ j(not_equal, &slow_case, not_taken); 2878 __ j(not_equal, &slow_case, not_taken);
2831 2879
2832 // SlicedString. 2880 // SlicedString.
2833 // Add the offset to the index. 2881 // Add the offset to the index.
2834 __ add(ebx, FieldOperand(eax, SlicedString::kStartOffset)); 2882 __ add(ebx, FieldOperand(eax, SlicedString::kStartOffset));
2835 __ j(overflow, &slow_case); 2883 __ j(overflow, &slow_case);
2836 // Get the underlying string. 2884 // Get the underlying string.
2837 __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset)); 2885 __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset));
2838 __ jmp(&try_again_with_new_string); 2886 __ jmp(&try_again_with_new_string);
2839 2887
2840 __ bind(&slow_case); 2888 __ bind(&slow_case);
2841 __ push(Immediate(Factory::undefined_value())); 2889 frame_->Push(Immediate(Factory::undefined_value()));
2842 2890
2843 __ bind(&end); 2891 __ bind(&end);
2844 } 2892 }
2845 2893
2846 2894
2847 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 2895 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
2848 ASSERT(args->length() == 1); 2896 ASSERT(args->length() == 1);
2849 Load(args->at(0)); 2897 Load(args->at(0));
2850 Label answer; 2898 Label answer;
2851 // We need the CC bits to come out as not_equal in the case where the 2899 // We need the CC bits to come out as not_equal in the case where the
2852 // object is a smi. This can't be done with the usual test opcode so 2900 // object is a smi. This can't be done with the usual test opcode so
2853 // we copy the object to ecx and do some destructive ops on it that 2901 // we copy the object to ecx and do some destructive ops on it that
2854 // result in the right CC bits. 2902 // result in the right CC bits.
2855 __ pop(eax); 2903 frame_->Pop(eax);
2856 __ mov(ecx, Operand(eax)); 2904 __ mov(ecx, Operand(eax));
2857 __ and_(ecx, kSmiTagMask); 2905 __ and_(ecx, kSmiTagMask);
2858 __ xor_(ecx, kSmiTagMask); 2906 __ xor_(ecx, kSmiTagMask);
2859 __ j(not_equal, &answer, not_taken); 2907 __ j(not_equal, &answer, not_taken);
2860 // It is a heap object - get map. 2908 // It is a heap object - get map.
2861 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 2909 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
2862 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); 2910 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
2863 // Check if the object is a JS array or not. 2911 // Check if the object is a JS array or not.
2864 __ cmp(eax, JS_ARRAY_TYPE); 2912 __ cmp(eax, JS_ARRAY_TYPE);
2865 __ bind(&answer); 2913 __ bind(&answer);
2866 cc_reg_ = equal; 2914 cc_reg_ = equal;
2867 } 2915 }
2868 2916
2869 2917
2870 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 2918 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
2871 ASSERT(args->length() == 0); 2919 ASSERT(args->length() == 0);
2872 2920
2873 // Seed the result with the formal parameters count, which will be 2921 // Seed the result with the formal parameters count, which will be
2874 // used in case no arguments adaptor frame is found below the 2922 // used in case no arguments adaptor frame is found below the
2875 // current frame. 2923 // current frame.
2876 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); 2924 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
2877 2925
2878 // Call the shared stub to get to the arguments.length. 2926 // Call the shared stub to get to the arguments.length.
2879 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); 2927 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
2880 __ CallStub(&stub); 2928 __ CallStub(&stub);
2881 __ push(eax); 2929 frame_->Push(eax);
2882 } 2930 }
2883 2931
2884 2932
2885 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 2933 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
2886 ASSERT(args->length() == 1); 2934 ASSERT(args->length() == 1);
2887 Label leave; 2935 Label leave;
2888 Load(args->at(0)); // Load the object. 2936 Load(args->at(0)); // Load the object.
2889 __ mov(eax, TOS); 2937 __ mov(eax, frame_->Top());
2890 // if (object->IsSmi()) return object. 2938 // if (object->IsSmi()) return object.
2891 __ test(eax, Immediate(kSmiTagMask)); 2939 __ test(eax, Immediate(kSmiTagMask));
2892 __ j(zero, &leave, taken); 2940 __ j(zero, &leave, taken);
2893 // It is a heap object - get map. 2941 // It is a heap object - get map.
2894 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 2942 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
2895 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 2943 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
2896 // if (!object->IsJSValue()) return object. 2944 // if (!object->IsJSValue()) return object.
2897 __ cmp(ecx, JS_VALUE_TYPE); 2945 __ cmp(ecx, JS_VALUE_TYPE);
2898 __ j(not_equal, &leave, not_taken); 2946 __ j(not_equal, &leave, not_taken);
2899 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); 2947 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
2900 __ mov(TOS, eax); 2948 __ mov(frame_->Top(), eax);
2901 __ bind(&leave); 2949 __ bind(&leave);
2902 } 2950 }
2903 2951
2904 2952
2905 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 2953 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
2906 ASSERT(args->length() == 2); 2954 ASSERT(args->length() == 2);
2907 Label leave; 2955 Label leave;
2908 Load(args->at(0)); // Load the object. 2956 Load(args->at(0)); // Load the object.
2909 Load(args->at(1)); // Load the value. 2957 Load(args->at(1)); // Load the value.
2910 __ mov(eax, (Operand(esp, kPointerSize))); 2958 __ mov(eax, frame_->Element(1));
2911 __ mov(ecx, TOS); 2959 __ mov(ecx, frame_->Top());
2912 // if (object->IsSmi()) return object. 2960 // if (object->IsSmi()) return object.
2913 __ test(eax, Immediate(kSmiTagMask)); 2961 __ test(eax, Immediate(kSmiTagMask));
2914 __ j(zero, &leave, taken); 2962 __ j(zero, &leave, taken);
2915 // It is a heap object - get map. 2963 // It is a heap object - get map.
2916 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2964 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2917 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 2965 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
2918 // if (!object->IsJSValue()) return object. 2966 // if (!object->IsJSValue()) return object.
2919 __ cmp(ebx, JS_VALUE_TYPE); 2967 __ cmp(ebx, JS_VALUE_TYPE);
2920 __ j(not_equal, &leave, not_taken); 2968 __ j(not_equal, &leave, not_taken);
2921 // Store the value. 2969 // Store the value.
2922 __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx); 2970 __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx);
2923 // Update the write barrier. 2971 // Update the write barrier.
2924 __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx); 2972 __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx);
2925 // Leave. 2973 // Leave.
2926 __ bind(&leave); 2974 __ bind(&leave);
2927 __ mov(ecx, TOS); 2975 __ mov(ecx, frame_->Top());
2928 __ pop(eax); 2976 frame_->Pop(eax);
2929 __ mov(TOS, ecx); 2977 __ mov(frame_->Top(), ecx);
2930 } 2978 }
2931 2979
2932 2980
2933 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 2981 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
2934 ASSERT(args->length() == 1); 2982 ASSERT(args->length() == 1);
2935 2983
2936 // Load the key onto the stack and set register eax to the formal 2984 // Load the key onto the stack and set register eax to the formal
2937 // parameters count for the currently executing function. 2985 // parameters count for the currently executing function.
2938 Load(args->at(0)); 2986 Load(args->at(0));
2939 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); 2987 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
2940 2988
2941 // Call the shared stub to get to arguments[key]. 2989 // Call the shared stub to get to arguments[key].
2942 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2990 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2943 __ CallStub(&stub); 2991 __ CallStub(&stub);
2944 __ mov(TOS, eax); 2992 __ mov(frame_->Top(), eax);
2945 } 2993 }
2946 2994
2947 2995
2948 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 2996 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
2949 ASSERT(args->length() == 2); 2997 ASSERT(args->length() == 2);
2950 2998
2951 // Load the two objects into registers and perform the comparison. 2999 // Load the two objects into registers and perform the comparison.
2952 Load(args->at(0)); 3000 Load(args->at(0));
2953 Load(args->at(1)); 3001 Load(args->at(1));
2954 __ pop(eax); 3002 frame_->Pop(eax);
2955 __ pop(ecx); 3003 frame_->Pop(ecx);
2956 __ cmp(eax, Operand(ecx)); 3004 __ cmp(eax, Operand(ecx));
2957 cc_reg_ = equal; 3005 cc_reg_ = equal;
2958 } 3006 }
2959 3007
2960 3008
2961 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 3009 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
2962 if (CheckForInlineRuntimeCall(node)) return; 3010 if (CheckForInlineRuntimeCall(node)) return;
2963 3011
2964 ZoneList<Expression*>* args = node->arguments(); 3012 ZoneList<Expression*>* args = node->arguments();
2965 Comment cmnt(masm_, "[ CallRuntime"); 3013 Comment cmnt(masm_, "[ CallRuntime");
2966 Runtime::Function* function = node->function(); 3014 Runtime::Function* function = node->function();
2967 3015
2968 if (function == NULL) { 3016 if (function == NULL) {
2969 // Prepare stack for calling JS runtime function. 3017 // Prepare stack for calling JS runtime function.
2970 __ push(Immediate(node->name())); 3018 frame_->Push(Immediate(node->name()));
2971 // Push the builtins object found in the current global object. 3019 // Push the builtins object found in the current global object.
2972 __ mov(edx, GlobalObject()); 3020 __ mov(edx, GlobalObject());
2973 __ push(FieldOperand(edx, GlobalObject::kBuiltinsOffset)); 3021 frame_->Push(FieldOperand(edx, GlobalObject::kBuiltinsOffset));
2974 } 3022 }
2975 3023
2976 // Push the arguments ("left-to-right"). 3024 // Push the arguments ("left-to-right").
2977 for (int i = 0; i < args->length(); i++) 3025 for (int i = 0; i < args->length(); i++)
2978 Load(args->at(i)); 3026 Load(args->at(i));
2979 3027
2980 if (function != NULL) { 3028 if (function != NULL) {
2981 // Call the C runtime function. 3029 // Call the C runtime function.
2982 __ CallRuntime(function, args->length()); 3030 __ CallRuntime(function, args->length());
2983 __ push(eax); 3031 frame_->Push(eax);
2984 } else { 3032 } else {
2985 // Call the JS runtime function. 3033 // Call the JS runtime function.
2986 Handle<Code> stub = ComputeCallInitialize(args->length()); 3034 Handle<Code> stub = ComputeCallInitialize(args->length());
2987 __ Set(eax, Immediate(args->length())); 3035 __ Set(eax, Immediate(args->length()));
2988 __ call(stub, RelocInfo::CODE_TARGET); 3036 __ call(stub, RelocInfo::CODE_TARGET);
2989 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3037 __ mov(esi, frame_->Context());
2990 __ mov(TOS, eax); 3038 __ mov(frame_->Top(), eax);
2991 } 3039 }
2992 } 3040 }
2993 3041
2994 3042
2995 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 3043 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
2996 Comment cmnt(masm_, "[ UnaryOperation"); 3044 Comment cmnt(masm_, "[ UnaryOperation");
2997 3045
2998 Token::Value op = node->op(); 3046 Token::Value op = node->op();
2999 3047
3000 if (op == Token::NOT) { 3048 if (op == Token::NOT) {
3001 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, 3049 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF,
3002 false_target(), true_target(), true); 3050 false_target(), true_target(), true);
3003 cc_reg_ = NegateCondition(cc_reg_); 3051 cc_reg_ = NegateCondition(cc_reg_);
3004 3052
3005 } else if (op == Token::DELETE) { 3053 } else if (op == Token::DELETE) {
3006 Property* property = node->expression()->AsProperty(); 3054 Property* property = node->expression()->AsProperty();
3007 if (property != NULL) { 3055 if (property != NULL) {
3008 Load(property->obj()); 3056 Load(property->obj());
3009 Load(property->key()); 3057 Load(property->key());
3010 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3058 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3011 __ push(eax); 3059 frame_->Push(eax);
3012 return; 3060 return;
3013 } 3061 }
3014 3062
3015 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); 3063 Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
3016 if (variable != NULL) { 3064 if (variable != NULL) {
3017 Slot* slot = variable->slot(); 3065 Slot* slot = variable->slot();
3018 if (variable->is_global()) { 3066 if (variable->is_global()) {
3019 LoadGlobal(); 3067 LoadGlobal();
3020 __ push(Immediate(variable->name())); 3068 frame_->Push(Immediate(variable->name()));
3021 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3069 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3022 __ push(eax); 3070 frame_->Push(eax);
3023 return; 3071 return;
3024 3072
3025 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 3073 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
3026 // lookup the context holding the named variable 3074 // lookup the context holding the named variable
3027 __ push(Operand(esi)); 3075 frame_->Push(esi);
3028 __ push(Immediate(variable->name())); 3076 frame_->Push(Immediate(variable->name()));
3029 __ CallRuntime(Runtime::kLookupContext, 2); 3077 __ CallRuntime(Runtime::kLookupContext, 2);
3030 // eax: context 3078 // eax: context
3031 __ push(eax); 3079 frame_->Push(eax);
3032 __ push(Immediate(variable->name())); 3080 frame_->Push(Immediate(variable->name()));
3033 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3081 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3034 __ push(eax); 3082 frame_->Push(eax);
3035 return; 3083 return;
3036 } 3084 }
3037 3085
3038 // Default: Result of deleting non-global, not dynamically 3086 // Default: Result of deleting non-global, not dynamically
3039 // introduced variables is false. 3087 // introduced variables is false.
3040 __ push(Immediate(Factory::false_value())); 3088 frame_->Push(Immediate(Factory::false_value()));
3041 3089
3042 } else { 3090 } else {
3043 // Default: Result of deleting expressions is true. 3091 // Default: Result of deleting expressions is true.
3044 Load(node->expression()); // may have side-effects 3092 Load(node->expression()); // may have side-effects
3045 __ Set(TOS, Immediate(Factory::true_value())); 3093 __ Set(frame_->Top(), Immediate(Factory::true_value()));
3046 } 3094 }
3047 3095
3048 } else if (op == Token::TYPEOF) { 3096 } else if (op == Token::TYPEOF) {
3049 // Special case for loading the typeof expression; see comment on 3097 // Special case for loading the typeof expression; see comment on
3050 // LoadTypeofExpression(). 3098 // LoadTypeofExpression().
3051 LoadTypeofExpression(node->expression()); 3099 LoadTypeofExpression(node->expression());
3052 __ CallRuntime(Runtime::kTypeof, 1); 3100 __ CallRuntime(Runtime::kTypeof, 1);
3053 __ push(eax); 3101 frame_->Push(eax);
3054 3102
3055 } else { 3103 } else {
3056 Load(node->expression()); 3104 Load(node->expression());
3057 switch (op) { 3105 switch (op) {
3058 case Token::NOT: 3106 case Token::NOT:
3059 case Token::DELETE: 3107 case Token::DELETE:
3060 case Token::TYPEOF: 3108 case Token::TYPEOF:
3061 UNREACHABLE(); // handled above 3109 UNREACHABLE(); // handled above
3062 break; 3110 break;
3063 3111
3064 case Token::SUB: { 3112 case Token::SUB: {
3065 UnarySubStub stub; 3113 UnarySubStub stub;
3066 // TODO(1222589): remove dependency of TOS being cached inside stub 3114 // TODO(1222589): remove dependency of TOS being cached inside stub
3067 __ pop(eax); 3115 frame_->Pop(eax);
3068 __ CallStub(&stub); 3116 __ CallStub(&stub);
3069 __ push(eax); 3117 frame_->Push(eax);
3070 break; 3118 break;
3071 } 3119 }
3072 3120
3073 case Token::BIT_NOT: { 3121 case Token::BIT_NOT: {
3074 // Smi check. 3122 // Smi check.
3075 Label smi_label; 3123 Label smi_label;
3076 Label continue_label; 3124 Label continue_label;
3077 __ pop(eax); 3125 frame_->Pop(eax);
3078 __ test(eax, Immediate(kSmiTagMask)); 3126 __ test(eax, Immediate(kSmiTagMask));
3079 __ j(zero, &smi_label, taken); 3127 __ j(zero, &smi_label, taken);
3080 3128
3081 __ push(eax); // undo popping of TOS 3129 frame_->Push(eax); // undo popping of TOS
3082 __ InvokeBuiltin(Builtins::BIT_NOT, CALL_FUNCTION); 3130 __ InvokeBuiltin(Builtins::BIT_NOT, CALL_FUNCTION);
3083 3131
3084 __ jmp(&continue_label); 3132 __ jmp(&continue_label);
3085 __ bind(&smi_label); 3133 __ bind(&smi_label);
3086 __ not_(eax); 3134 __ not_(eax);
3087 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag. 3135 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag.
3088 __ bind(&continue_label); 3136 __ bind(&continue_label);
3089 __ push(eax); 3137 frame_->Push(eax);
3090 break; 3138 break;
3091 } 3139 }
3092 3140
3093 case Token::VOID: 3141 case Token::VOID:
3094 __ mov(TOS, Factory::undefined_value()); 3142 __ mov(frame_->Top(), Factory::undefined_value());
3095 break; 3143 break;
3096 3144
3097 case Token::ADD: { 3145 case Token::ADD: {
3098 // Smi check. 3146 // Smi check.
3099 Label continue_label; 3147 Label continue_label;
3100 __ pop(eax); 3148 frame_->Pop(eax);
3101 __ test(eax, Immediate(kSmiTagMask)); 3149 __ test(eax, Immediate(kSmiTagMask));
3102 __ j(zero, &continue_label); 3150 __ j(zero, &continue_label);
3103 3151
3104 __ push(eax); 3152 frame_->Push(eax);
3105 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 3153 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
3106 3154
3107 __ bind(&continue_label); 3155 __ bind(&continue_label);
3108 __ push(eax); 3156 frame_->Push(eax);
3109 break; 3157 break;
3110 } 3158 }
3111 3159
3112 default: 3160 default:
3113 UNREACHABLE(); 3161 UNREACHABLE();
3114 } 3162 }
3115 } 3163 }
3116 } 3164 }
3117 3165
3118 3166
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
3204 void CodeGenerator::VisitCountOperation(CountOperation* node) { 3252 void CodeGenerator::VisitCountOperation(CountOperation* node) {
3205 Comment cmnt(masm_, "[ CountOperation"); 3253 Comment cmnt(masm_, "[ CountOperation");
3206 3254
3207 bool is_postfix = node->is_postfix(); 3255 bool is_postfix = node->is_postfix();
3208 bool is_increment = node->op() == Token::INC; 3256 bool is_increment = node->op() == Token::INC;
3209 3257
3210 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 3258 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
3211 bool is_const = (var != NULL && var->mode() == Variable::CONST); 3259 bool is_const = (var != NULL && var->mode() == Variable::CONST);
3212 3260
3213 // Postfix: Make room for the result. 3261 // Postfix: Make room for the result.
3214 if (is_postfix) __ push(Immediate(0)); 3262 if (is_postfix) {
3263 frame_->Push(Immediate(0));
3264 }
3215 3265
3216 { Reference target(this, node->expression()); 3266 { Reference target(this, node->expression());
3217 if (target.is_illegal()) return; 3267 if (target.is_illegal()) return;
3218 target.GetValue(NOT_INSIDE_TYPEOF); 3268 target.GetValue(NOT_INSIDE_TYPEOF);
3219 3269
3220 int result_offset = target.size() * kPointerSize;
3221 CountOperationDeferred* deferred = 3270 CountOperationDeferred* deferred =
3222 new CountOperationDeferred(this, is_postfix, 3271 new CountOperationDeferred(this, is_postfix, is_increment,
3223 is_increment, result_offset); 3272 target.size() * kPointerSize);
3224 3273
3225 __ pop(eax); // Load TOS into eax for calculations below 3274 frame_->Pop(eax); // Load TOS into eax for calculations below
3226 3275
3227 // Postfix: Store the old value as the result. 3276 // Postfix: Store the old value as the result.
3228 if (is_postfix) __ mov(Operand(esp, result_offset), eax); 3277 if (is_postfix) {
3278 __ mov(frame_->Element(target.size()), eax);
3279 }
3229 3280
3230 // Perform optimistic increment/decrement. 3281 // Perform optimistic increment/decrement.
3231 if (is_increment) { 3282 if (is_increment) {
3232 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3283 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3233 } else { 3284 } else {
3234 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3285 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3235 } 3286 }
3236 3287
3237 // If the count operation didn't overflow and the result is a 3288 // If the count operation didn't overflow and the result is a
3238 // valid smi, we're done. Otherwise, we jump to the deferred 3289 // valid smi, we're done. Otherwise, we jump to the deferred
3239 // slow-case code. 3290 // slow-case code.
3240 __ j(overflow, deferred->enter(), not_taken); 3291 __ j(overflow, deferred->enter(), not_taken);
3241 __ test(eax, Immediate(kSmiTagMask)); 3292 __ test(eax, Immediate(kSmiTagMask));
3242 __ j(not_zero, deferred->enter(), not_taken); 3293 __ j(not_zero, deferred->enter(), not_taken);
3243 3294
3244 // Store the new value in the target if not const. 3295 // Store the new value in the target if not const.
3245 __ bind(deferred->exit()); 3296 __ bind(deferred->exit());
3246 __ push(eax); // Push the new value to TOS 3297 frame_->Push(eax); // Push the new value to TOS
3247 if (!is_const) target.SetValue(NOT_CONST_INIT); 3298 if (!is_const) target.SetValue(NOT_CONST_INIT);
3248 } 3299 }
3249 3300
3250 // Postfix: Discard the new value and use the old. 3301 // Postfix: Discard the new value and use the old.
3251 if (is_postfix) __ pop(eax); 3302 if (is_postfix) {
3303 frame_->Pop(eax);
3304 }
3252 } 3305 }
3253 3306
3254 3307
3255 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 3308 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
3256 Comment cmnt(masm_, "[ BinaryOperation"); 3309 Comment cmnt(masm_, "[ BinaryOperation");
3257 Token::Value op = node->op(); 3310 Token::Value op = node->op();
3258 3311
3259 // According to ECMA-262 section 11.11, page 58, the binary logical 3312 // According to ECMA-262 section 11.11, page 58, the binary logical
3260 // operators must yield the result of one of the two expressions 3313 // operators must yield the result of one of the two expressions
3261 // before any ToBoolean() conversions. This means that the value 3314 // before any ToBoolean() conversions. This means that the value
(...skipping 18 matching lines...) Expand all
3280 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(), 3333 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(),
3281 false_target(), false); 3334 false_target(), false);
3282 3335
3283 } else { 3336 } else {
3284 Label pop_and_continue, exit; 3337 Label pop_and_continue, exit;
3285 3338
3286 // Avoid popping the result if it converts to 'false' using the 3339 // Avoid popping the result if it converts to 'false' using the
3287 // standard ToBoolean() conversion as described in ECMA-262, 3340 // standard ToBoolean() conversion as described in ECMA-262,
3288 // section 9.2, page 30. 3341 // section 9.2, page 30.
3289 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3342 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3290 __ mov(eax, TOS); 3343 __ mov(eax, frame_->Top());
3291 __ push(eax); 3344 frame_->Push(eax);
3292 ToBoolean(&pop_and_continue, &exit); 3345 ToBoolean(&pop_and_continue, &exit);
3293 Branch(false, &exit); 3346 Branch(false, &exit);
3294 3347
3295 // Pop the result of evaluating the first part. 3348 // Pop the result of evaluating the first part.
3296 __ bind(&pop_and_continue); 3349 __ bind(&pop_and_continue);
3297 __ pop(eax); 3350 frame_->Pop(eax);
3298 3351
3299 // Evaluate right side expression. 3352 // Evaluate right side expression.
3300 __ bind(&is_true); 3353 __ bind(&is_true);
3301 Load(node->right()); 3354 Load(node->right());
3302 3355
3303 // Exit (always with a materialized value). 3356 // Exit (always with a materialized value).
3304 __ bind(&exit); 3357 __ bind(&exit);
3305 } 3358 }
3306 3359
3307 } else if (op == Token::OR) { 3360 } else if (op == Token::OR) {
3308 Label is_false; 3361 Label is_false;
3309 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, true_target(), 3362 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, true_target(),
3310 &is_false, false); 3363 &is_false, false);
3311 if (has_cc()) { 3364 if (has_cc()) {
3312 Branch(true, true_target()); 3365 Branch(true, true_target());
3313 3366
3314 // Evaluate right side expression. 3367 // Evaluate right side expression.
3315 __ bind(&is_false); 3368 __ bind(&is_false);
3316 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(), 3369 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(),
3317 false_target(), false); 3370 false_target(), false);
3318 3371
3319 } else { 3372 } else {
3320 Label pop_and_continue, exit; 3373 Label pop_and_continue, exit;
3321 3374
3322 // Avoid popping the result if it converts to 'true' using the 3375 // Avoid popping the result if it converts to 'true' using the
3323 // standard ToBoolean() conversion as described in ECMA-262, 3376 // standard ToBoolean() conversion as described in ECMA-262,
3324 // section 9.2, page 30. 3377 // section 9.2, page 30.
3325 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3378 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3326 __ mov(eax, TOS); 3379 __ mov(eax, frame_->Top());
3327 __ push(eax); 3380 frame_->Push(eax);
3328 ToBoolean(&exit, &pop_and_continue); 3381 ToBoolean(&exit, &pop_and_continue);
3329 Branch(true, &exit); 3382 Branch(true, &exit);
3330 3383
3331 // Pop the result of evaluating the first part. 3384 // Pop the result of evaluating the first part.
3332 __ bind(&pop_and_continue); 3385 __ bind(&pop_and_continue);
3333 __ pop(eax); 3386 frame_->Pop(eax);
3334 3387
3335 // Evaluate right side expression. 3388 // Evaluate right side expression.
3336 __ bind(&is_false); 3389 __ bind(&is_false);
3337 Load(node->right()); 3390 Load(node->right());
3338 3391
3339 // Exit (always with a materialized value). 3392 // Exit (always with a materialized value).
3340 __ bind(&exit); 3393 __ bind(&exit);
3341 } 3394 }
3342 3395
3343 } else { 3396 } else {
(...skipping 24 matching lines...) Expand all
3368 } else { 3421 } else {
3369 Load(node->left()); 3422 Load(node->left());
3370 Load(node->right()); 3423 Load(node->right());
3371 GenericBinaryOperation(node->op(), overwrite_mode); 3424 GenericBinaryOperation(node->op(), overwrite_mode);
3372 } 3425 }
3373 } 3426 }
3374 } 3427 }
3375 3428
3376 3429
3377 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 3430 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
3378 __ push(FunctionOperand()); 3431 frame_->Push(frame_->Function());
3379 } 3432 }
3380 3433
3381 3434
3382 class InstanceofStub: public CodeStub { 3435 class InstanceofStub: public CodeStub {
3383 public: 3436 public:
3384 InstanceofStub() { } 3437 InstanceofStub() { }
3385 3438
3386 void Generate(MacroAssembler* masm); 3439 void Generate(MacroAssembler* masm);
3387 3440
3388 private: 3441 private:
(...skipping 18 matching lines...) Expand all
3407 bool left_is_null = 3460 bool left_is_null =
3408 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); 3461 left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
3409 bool right_is_null = 3462 bool right_is_null =
3410 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); 3463 right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
3411 3464
3412 if (op == Token::EQ || op == Token::EQ_STRICT) { 3465 if (op == Token::EQ || op == Token::EQ_STRICT) {
3413 // The 'null' value is only equal to 'null' or 'undefined'. 3466 // The 'null' value is only equal to 'null' or 'undefined'.
3414 if (left_is_null || right_is_null) { 3467 if (left_is_null || right_is_null) {
3415 Load(left_is_null ? right : left); 3468 Load(left_is_null ? right : left);
3416 Label exit, undetectable; 3469 Label exit, undetectable;
3417 __ pop(eax); 3470 frame_->Pop(eax);
3418 __ cmp(eax, Factory::null_value()); 3471 __ cmp(eax, Factory::null_value());
3419 3472
3420 // The 'null' value is only equal to 'undefined' if using 3473 // The 'null' value is only equal to 'undefined' if using
3421 // non-strict comparisons. 3474 // non-strict comparisons.
3422 if (op != Token::EQ_STRICT) { 3475 if (op != Token::EQ_STRICT) {
3423 __ j(equal, &exit); 3476 __ j(equal, &exit);
3424 __ cmp(eax, Factory::undefined_value()); 3477 __ cmp(eax, Factory::undefined_value());
3425 3478
3426 // NOTE: it can be an undetectable object. 3479 // NOTE: it can be an undetectable object.
3427 __ j(equal, &exit); 3480 __ j(equal, &exit);
(...skipping 23 matching lines...) Expand all
3451 3504
3452 UnaryOperation* operation = left->AsUnaryOperation(); 3505 UnaryOperation* operation = left->AsUnaryOperation();
3453 if ((op == Token::EQ || op == Token::EQ_STRICT) && 3506 if ((op == Token::EQ || op == Token::EQ_STRICT) &&
3454 (operation != NULL && operation->op() == Token::TYPEOF) && 3507 (operation != NULL && operation->op() == Token::TYPEOF) &&
3455 (right->AsLiteral() != NULL && 3508 (right->AsLiteral() != NULL &&
3456 right->AsLiteral()->handle()->IsString())) { 3509 right->AsLiteral()->handle()->IsString())) {
3457 Handle<String> check(String::cast(*right->AsLiteral()->handle())); 3510 Handle<String> check(String::cast(*right->AsLiteral()->handle()));
3458 3511
3459 // Load the operand, move it to register edx, and restore TOS. 3512 // Load the operand, move it to register edx, and restore TOS.
3460 LoadTypeofExpression(operation->expression()); 3513 LoadTypeofExpression(operation->expression());
3461 __ pop(edx); 3514 frame_->Pop(edx);
3462 3515
3463 if (check->Equals(Heap::number_symbol())) { 3516 if (check->Equals(Heap::number_symbol())) {
3464 __ test(edx, Immediate(kSmiTagMask)); 3517 __ test(edx, Immediate(kSmiTagMask));
3465 __ j(zero, true_target()); 3518 __ j(zero, true_target());
3466 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 3519 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
3467 __ cmp(edx, Factory::heap_number_map()); 3520 __ cmp(edx, Factory::heap_number_map());
3468 cc_reg_ = equal; 3521 cc_reg_ = equal;
3469 3522
3470 } else if (check->Equals(Heap::string_symbol())) { 3523 } else if (check->Equals(Heap::string_symbol())) {
3471 __ test(edx, Immediate(kSmiTagMask)); 3524 __ test(edx, Immediate(kSmiTagMask));
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
3558 case Token::LTE: 3611 case Token::LTE:
3559 cc = less_equal; 3612 cc = less_equal;
3560 break; 3613 break;
3561 case Token::GTE: 3614 case Token::GTE:
3562 cc = greater_equal; 3615 cc = greater_equal;
3563 break; 3616 break;
3564 case Token::IN: { 3617 case Token::IN: {
3565 Load(left); 3618 Load(left);
3566 Load(right); 3619 Load(right);
3567 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3620 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3568 __ push(eax); // push the result 3621 frame_->Push(eax); // push the result
3569 return; 3622 return;
3570 } 3623 }
3571 case Token::INSTANCEOF: { 3624 case Token::INSTANCEOF: {
3572 Load(left); 3625 Load(left);
3573 Load(right); 3626 Load(right);
3574 InstanceofStub stub; 3627 InstanceofStub stub;
3575 __ CallStub(&stub); 3628 __ CallStub(&stub);
3576 __ test(eax, Operand(eax)); 3629 __ test(eax, Operand(eax));
3577 cc_reg_ = zero; 3630 cc_reg_ = zero;
3578 return; 3631 return;
(...skipping 24 matching lines...) Expand all
3603 void CodeGenerator::RecordStatementPosition(Node* node) { 3656 void CodeGenerator::RecordStatementPosition(Node* node) {
3604 if (FLAG_debug_info) { 3657 if (FLAG_debug_info) {
3605 int pos = node->statement_pos(); 3658 int pos = node->statement_pos();
3606 if (pos != RelocInfo::kNoPosition) { 3659 if (pos != RelocInfo::kNoPosition) {
3607 __ RecordStatementPosition(pos); 3660 __ RecordStatementPosition(pos);
3608 } 3661 }
3609 } 3662 }
3610 } 3663 }
3611 3664
3612 3665
3613 void CodeGenerator::EnterJSFrame() { 3666 void VirtualFrame::Enter() {
3667 Comment cmnt(masm_, "[ Enter JS frame");
3614 __ push(ebp); 3668 __ push(ebp);
3615 __ mov(ebp, Operand(esp)); 3669 __ mov(ebp, Operand(esp));
3616 3670
3617 // Store the context and the function in the frame. 3671 // Store the context and the function in the frame.
3618 __ push(esi); 3672 __ push(esi);
3619 __ push(edi); 3673 __ push(edi);
3620 3674
3621 // Clear the function slot when generating debug code. 3675 // Clear the function slot when generating debug code.
3622 if (FLAG_debug_code) { 3676 if (FLAG_debug_code) {
3623 __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue))); 3677 __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue)));
3624 } 3678 }
3625 } 3679 }
3626 3680
3627 3681
3628 void CodeGenerator::ExitJSFrame() { 3682 void VirtualFrame::Exit() {
3683 Comment cmnt(masm_, "[ Exit JS frame");
3629 // Record the location of the JS exit code for patching when setting 3684 // Record the location of the JS exit code for patching when setting
3630 // break point. 3685 // break point.
3631 __ RecordJSReturn(); 3686 __ RecordJSReturn();
3632 3687
3633 // Avoid using the leave instruction here, because it is too 3688 // Avoid using the leave instruction here, because it is too
3634 // short. We need the return sequence to be a least the size of a 3689 // short. We need the return sequence to be a least the size of a
3635 // call instruction to support patching the exit code in the 3690 // call instruction to support patching the exit code in the
3636 // debugger. See VisitReturnStatement for the full return sequence. 3691 // debugger. See VisitReturnStatement for the full return sequence.
3637 __ mov(esp, Operand(ebp)); 3692 __ mov(esp, Operand(ebp));
3638 __ pop(ebp); 3693 __ pop(ebp);
(...skipping 19 matching lines...) Expand all
3658 ASSERT(raw_name != NULL); 3713 ASSERT(raw_name != NULL);
3659 return Handle<String>(String::cast(*raw_name->handle())); 3714 return Handle<String>(String::cast(*raw_name->handle()));
3660 } 3715 }
3661 } 3716 }
3662 3717
3663 3718
3664 void Reference::GetValue(TypeofState typeof_state) { 3719 void Reference::GetValue(TypeofState typeof_state) {
3665 ASSERT(!is_illegal()); 3720 ASSERT(!is_illegal());
3666 ASSERT(!cgen_->has_cc()); 3721 ASSERT(!cgen_->has_cc());
3667 MacroAssembler* masm = cgen_->masm(); 3722 MacroAssembler* masm = cgen_->masm();
3723 VirtualFrame* frame = cgen_->frame();
3668 switch (type_) { 3724 switch (type_) {
3669 case SLOT: { 3725 case SLOT: {
3670 Comment cmnt(masm, "[ Load from Slot"); 3726 Comment cmnt(masm, "[ Load from Slot");
3671 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 3727 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
3672 ASSERT(slot != NULL); 3728 ASSERT(slot != NULL);
3673 cgen_->LoadFromSlot(slot, typeof_state); 3729 cgen_->LoadFromSlot(slot, typeof_state);
3674 break; 3730 break;
3675 } 3731 }
3676 3732
3677 case NAMED: { 3733 case NAMED: {
3678 // TODO(1241834): Make sure that this it is safe to ignore the 3734 // TODO(1241834): Make sure that this it is safe to ignore the
3679 // distinction between expressions in a typeof and not in a typeof. If 3735 // distinction between expressions in a typeof and not in a typeof. If
3680 // there is a chance that reference errors can be thrown below, we 3736 // there is a chance that reference errors can be thrown below, we
3681 // must distinguish between the two kinds of loads (typeof expression 3737 // must distinguish between the two kinds of loads (typeof expression
3682 // loads must not throw a reference error). 3738 // loads must not throw a reference error).
3683 Comment cmnt(masm, "[ Load from named Property"); 3739 Comment cmnt(masm, "[ Load from named Property");
3684 Handle<String> name(GetName()); 3740 Handle<String> name(GetName());
3685 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3741 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3686 // Setup the name register. 3742 // Setup the name register.
3687 __ mov(ecx, name); 3743 __ mov(ecx, name);
3688 3744
3689 Variable* var = expression_->AsVariableProxy()->AsVariable(); 3745 Variable* var = expression_->AsVariableProxy()->AsVariable();
3690 if (var != NULL) { 3746 if (var != NULL) {
3691 ASSERT(var->is_global()); 3747 ASSERT(var->is_global());
3692 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 3748 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
3693 } else { 3749 } else {
3694 __ call(ic, RelocInfo::CODE_TARGET); 3750 __ call(ic, RelocInfo::CODE_TARGET);
3695 } 3751 }
3696 __ push(eax); // IC call leaves result in eax, push it out 3752 frame->Push(eax); // IC call leaves result in eax, push it out
3697 break; 3753 break;
3698 } 3754 }
3699 3755
3700 case KEYED: { 3756 case KEYED: {
3701 // TODO(1241834): Make sure that this it is safe to ignore the 3757 // TODO(1241834): Make sure that this it is safe to ignore the
3702 // distinction between expressions in a typeof and not in a typeof. 3758 // distinction between expressions in a typeof and not in a typeof.
3703 Comment cmnt(masm, "[ Load from keyed Property"); 3759 Comment cmnt(masm, "[ Load from keyed Property");
3704 Property* property = expression_->AsProperty(); 3760 Property* property = expression_->AsProperty();
3705 ASSERT(property != NULL); 3761 ASSERT(property != NULL);
3706 __ RecordPosition(property->position()); 3762 __ RecordPosition(property->position());
3707 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 3763 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
3708 3764
3709 Variable* var = expression_->AsVariableProxy()->AsVariable(); 3765 Variable* var = expression_->AsVariableProxy()->AsVariable();
3710 if (var != NULL) { 3766 if (var != NULL) {
3711 ASSERT(var->is_global()); 3767 ASSERT(var->is_global());
3712 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 3768 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
3713 } else { 3769 } else {
3714 __ call(ic, RelocInfo::CODE_TARGET); 3770 __ call(ic, RelocInfo::CODE_TARGET);
3715 } 3771 }
3716 __ push(eax); // IC call leaves result in eax, push it out 3772 frame->Push(eax); // IC call leaves result in eax, push it out
3717 break; 3773 break;
3718 } 3774 }
3719 3775
3720 default: 3776 default:
3721 UNREACHABLE(); 3777 UNREACHABLE();
3722 } 3778 }
3723 } 3779 }
3724 3780
3725 3781
3726 void Reference::SetValue(InitState init_state) { 3782 void Reference::SetValue(InitState init_state) {
3727 ASSERT(!is_illegal()); 3783 ASSERT(!is_illegal());
3728 ASSERT(!cgen_->has_cc()); 3784 ASSERT(!cgen_->has_cc());
3729 MacroAssembler* masm = cgen_->masm(); 3785 MacroAssembler* masm = cgen_->masm();
3786 VirtualFrame* frame = cgen_->frame();
3730 switch (type_) { 3787 switch (type_) {
3731 case SLOT: { 3788 case SLOT: {
3732 Comment cmnt(masm, "[ Store to Slot"); 3789 Comment cmnt(masm, "[ Store to Slot");
3733 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 3790 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
3734 ASSERT(slot != NULL); 3791 ASSERT(slot != NULL);
3735 if (slot->type() == Slot::LOOKUP) { 3792 if (slot->type() == Slot::LOOKUP) {
3736 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 3793 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
3737 3794
3738 // For now, just do a runtime call. 3795 // For now, just do a runtime call.
3739 __ push(esi); 3796 frame->Push(esi);
3740 __ push(Immediate(slot->var()->name())); 3797 frame->Push(Immediate(slot->var()->name()));
3741 3798
3742 if (init_state == CONST_INIT) { 3799 if (init_state == CONST_INIT) {
3743 // Same as the case for a normal store, but ignores attribute 3800 // Same as the case for a normal store, but ignores attribute
3744 // (e.g. READ_ONLY) of context slot so that we can initialize 3801 // (e.g. READ_ONLY) of context slot so that we can initialize
3745 // const properties (introduced via eval("const foo = (some 3802 // const properties (introduced via eval("const foo = (some
3746 // expr);")). Also, uses the current function context instead of 3803 // expr);")). Also, uses the current function context instead of
3747 // the top context. 3804 // the top context.
3748 // 3805 //
3749 // Note that we must declare the foo upon entry of eval(), via a 3806 // Note that we must declare the foo upon entry of eval(), via a
3750 // context slot declaration, but we cannot initialize it at the 3807 // context slot declaration, but we cannot initialize it at the
3751 // same time, because the const declaration may be at the end of 3808 // same time, because the const declaration may be at the end of
3752 // the eval code (sigh...) and the const variable may have been 3809 // the eval code (sigh...) and the const variable may have been
3753 // used before (where its value is 'undefined'). Thus, we can only 3810 // used before (where its value is 'undefined'). Thus, we can only
3754 // do the initialization when we actually encounter the expression 3811 // do the initialization when we actually encounter the expression
3755 // and when the expression operands are defined and valid, and 3812 // and when the expression operands are defined and valid, and
3756 // thus we need the split into 2 operations: declaration of the 3813 // thus we need the split into 2 operations: declaration of the
3757 // context slot followed by initialization. 3814 // context slot followed by initialization.
3758 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 3815 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
3759 } else { 3816 } else {
3760 __ CallRuntime(Runtime::kStoreContextSlot, 3); 3817 __ CallRuntime(Runtime::kStoreContextSlot, 3);
3761 } 3818 }
3762 // Storing a variable must keep the (new) value on the expression 3819 // Storing a variable must keep the (new) value on the expression
3763 // stack. This is necessary for compiling chained assignment 3820 // stack. This is necessary for compiling chained assignment
3764 // expressions. 3821 // expressions.
3765 __ push(eax); 3822 frame->Push(eax);
3766 3823
3767 } else { 3824 } else {
3768 ASSERT(slot->var()->mode() != Variable::DYNAMIC); 3825 ASSERT(slot->var()->mode() != Variable::DYNAMIC);
3769 3826
3770 Label exit; 3827 Label exit;
3771 if (init_state == CONST_INIT) { 3828 if (init_state == CONST_INIT) {
3772 ASSERT(slot->var()->mode() == Variable::CONST); 3829 ASSERT(slot->var()->mode() == Variable::CONST);
3773 // Only the first const initialization must be executed (the slot 3830 // Only the first const initialization must be executed (the slot
3774 // still contains 'the hole' value). When the assignment is 3831 // still contains 'the hole' value). When the assignment is
3775 // executed, the code is identical to a normal store (see below). 3832 // executed, the code is identical to a normal store (see below).
3776 Comment cmnt(masm, "[ Init const"); 3833 Comment cmnt(masm, "[ Init const");
3777 __ mov(eax, cgen_->SlotOperand(slot, ecx)); 3834 __ mov(eax, cgen_->SlotOperand(slot, ecx));
3778 __ cmp(eax, Factory::the_hole_value()); 3835 __ cmp(eax, Factory::the_hole_value());
3779 __ j(not_equal, &exit); 3836 __ j(not_equal, &exit);
3780 } 3837 }
3781 3838
3782 // We must execute the store. Storing a variable must keep the 3839 // We must execute the store. Storing a variable must keep the
3783 // (new) value on the stack. This is necessary for compiling 3840 // (new) value on the stack. This is necessary for compiling
3784 // assignment expressions. 3841 // assignment expressions.
3785 // 3842 //
3786 // Note: We will reach here even with slot->var()->mode() == 3843 // Note: We will reach here even with slot->var()->mode() ==
3787 // Variable::CONST because of const declarations which will 3844 // Variable::CONST because of const declarations which will
3788 // initialize consts to 'the hole' value and by doing so, end up 3845 // initialize consts to 'the hole' value and by doing so, end up
3789 // calling this code. 3846 // calling this code.
3790 __ pop(eax); 3847 __ pop(eax);
3791 __ mov(cgen_->SlotOperand(slot, ecx), eax); 3848 __ mov(cgen_->SlotOperand(slot, ecx), eax);
3792 __ push(eax); // RecordWrite may destroy the value in eax. 3849 frame->Push(eax); // RecordWrite may destroy the value in eax.
3793 if (slot->type() == Slot::CONTEXT) { 3850 if (slot->type() == Slot::CONTEXT) {
3794 // ecx is loaded with context when calling SlotOperand above. 3851 // ecx is loaded with context when calling SlotOperand above.
3795 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 3852 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
3796 __ RecordWrite(ecx, offset, eax, ebx); 3853 __ RecordWrite(ecx, offset, eax, ebx);
3797 } 3854 }
3798 // If we definitely did not jump over the assignment, we do not need 3855 // If we definitely did not jump over the assignment, we do not need
3799 // to bind the exit label. Doing so can defeat peephole 3856 // to bind the exit label. Doing so can defeat peephole
3800 // optimization. 3857 // optimization.
3801 if (init_state == CONST_INIT) __ bind(&exit); 3858 if (init_state == CONST_INIT) __ bind(&exit);
3802 } 3859 }
3803 break; 3860 break;
3804 } 3861 }
3805 3862
3806 case NAMED: { 3863 case NAMED: {
3807 Comment cmnt(masm, "[ Store to named Property"); 3864 Comment cmnt(masm, "[ Store to named Property");
3808 // Call the appropriate IC code. 3865 // Call the appropriate IC code.
3809 Handle<String> name(GetName()); 3866 Handle<String> name(GetName());
3810 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3867 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3811 // TODO(1222589): Make the IC grab the values from the stack. 3868 // TODO(1222589): Make the IC grab the values from the stack.
3812 __ pop(eax); 3869 __ pop(eax);
3813 // Setup the name register. 3870 // Setup the name register.
3814 __ mov(ecx, name); 3871 __ mov(ecx, name);
3815 __ call(ic, RelocInfo::CODE_TARGET); 3872 __ call(ic, RelocInfo::CODE_TARGET);
3816 __ push(eax); // IC call leaves result in eax, push it out 3873 frame->Push(eax); // IC call leaves result in eax, push it out
3817 break; 3874 break;
3818 } 3875 }
3819 3876
3820 case KEYED: { 3877 case KEYED: {
3821 Comment cmnt(masm, "[ Store to keyed Property"); 3878 Comment cmnt(masm, "[ Store to keyed Property");
3822 Property* property = expression_->AsProperty(); 3879 Property* property = expression_->AsProperty();
3823 ASSERT(property != NULL); 3880 ASSERT(property != NULL);
3824 __ RecordPosition(property->position()); 3881 __ RecordPosition(property->position());
3825 // Call IC code. 3882 // Call IC code.
3826 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 3883 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
3827 // TODO(1222589): Make the IC grab the values from the stack. 3884 // TODO(1222589): Make the IC grab the values from the stack.
3828 __ pop(eax); 3885 __ pop(eax);
3829 __ call(ic, RelocInfo::CODE_TARGET); 3886 __ call(ic, RelocInfo::CODE_TARGET);
3830 __ push(eax); // IC call leaves result in eax, push it out 3887 frame->Push(eax); // IC call leaves result in eax, push it out
3831 break; 3888 break;
3832 } 3889 }
3833 3890
3834 default: 3891 default:
3835 UNREACHABLE(); 3892 UNREACHABLE();
3836 } 3893 }
3837 } 3894 }
3838 3895
3839 3896
3840 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). 3897 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined).
(...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after
5046 5103
5047 // Slow-case: Go through the JavaScript implementation. 5104 // Slow-case: Go through the JavaScript implementation.
5048 __ bind(&slow); 5105 __ bind(&slow);
5049 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5106 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5050 } 5107 }
5051 5108
5052 5109
5053 #undef __ 5110 #undef __
5054 5111
5055 } } // namespace v8::internal 5112 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698