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

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

Issue 555073: Merge r3610, r3611, r3612, r3630, r3636, r3640, and r3664... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 11 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/fast-codegen.cc ('k') | src/runtime.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "codegen-inl.h" 30 #include "codegen-inl.h"
31 #include "compiler.h" 31 #include "compiler.h"
32 #include "debug.h"
32 #include "fast-codegen.h" 33 #include "fast-codegen.h"
33 #include "parser.h" 34 #include "parser.h"
34 #include "debug.h"
35 35
36 namespace v8 { 36 namespace v8 {
37 namespace internal { 37 namespace internal {
38 38
39 #define __ ACCESS_MASM(masm_) 39 #define __ ACCESS_MASM(masm_)
40 40
41 // Generate code for a JS function. On entry to the function the receiver 41 // Generate code for a JS function. On entry to the function the receiver
42 // and arguments have been pushed on the stack left to right, with the 42 // and arguments have been pushed on the stack left to right, with the
43 // return address on top of them. The actual argument count matches the 43 // return address on top of them. The actual argument count matches the
44 // formal parameter count expected by the function. 44 // formal parameter count expected by the function.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 } else { 109 } else {
110 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 110 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
111 } 111 }
112 // Receiver is just before the parameters on the caller's stack. 112 // Receiver is just before the parameters on the caller's stack.
113 __ lea(edx, Operand(ebp, StandardFrameConstants::kCallerSPOffset + 113 __ lea(edx, Operand(ebp, StandardFrameConstants::kCallerSPOffset +
114 fun->num_parameters() * kPointerSize)); 114 fun->num_parameters() * kPointerSize));
115 __ push(edx); 115 __ push(edx);
116 __ push(Immediate(Smi::FromInt(fun->num_parameters()))); 116 __ push(Immediate(Smi::FromInt(fun->num_parameters())));
117 // Arguments to ArgumentsAccessStub: 117 // Arguments to ArgumentsAccessStub:
118 // function, receiver address, parameter count. 118 // function, receiver address, parameter count.
119 // The stub will rewrite receiever and parameter count if the previous 119 // The stub will rewrite receiver and parameter count if the previous
120 // stack frame was an arguments adapter frame. 120 // stack frame was an arguments adapter frame.
121 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 121 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
122 __ CallStub(&stub); 122 __ CallStub(&stub);
123 __ mov(ecx, eax); // Duplicate result. 123 __ mov(ecx, eax); // Duplicate result.
124 Move(arguments->slot(), eax, ebx, edx); 124 Move(arguments->slot(), eax, ebx, edx);
125 Slot* dot_arguments_slot = 125 Slot* dot_arguments_slot =
126 fun->scope()->arguments_shadow()->AsVariable()->slot(); 126 fun->scope()->arguments_shadow()->AsVariable()->slot();
127 Move(dot_arguments_slot, ecx, ebx, edx); 127 Move(dot_arguments_slot, ecx, ebx, edx);
128 } 128 }
129 129
130
131 { Comment cmnt(masm_, "[ Declarations"); 130 { Comment cmnt(masm_, "[ Declarations");
132 VisitDeclarations(fun->scope()->declarations()); 131 VisitDeclarations(fun->scope()->declarations());
133 } 132 }
134 133
135 { Comment cmnt(masm_, "[ Stack check"); 134 { Comment cmnt(masm_, "[ Stack check");
136 Label ok; 135 Label ok;
137 ExternalReference stack_limit = 136 ExternalReference stack_limit =
138 ExternalReference::address_of_stack_limit(); 137 ExternalReference::address_of_stack_limit();
139 __ cmp(esp, Operand::StaticVariable(stack_limit)); 138 __ cmp(esp, Operand::StaticVariable(stack_limit));
140 __ j(above_equal, &ok, taken); 139 __ j(above_equal, &ok, taken);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 #ifdef ENABLE_DEBUGGER_SUPPORT 186 #ifdef ENABLE_DEBUGGER_SUPPORT
188 // Check that the size of the code used for returning matches what is 187 // Check that the size of the code used for returning matches what is
189 // expected by the debugger. 188 // expected by the debugger.
190 ASSERT_EQ(Assembler::kJSReturnSequenceLength, 189 ASSERT_EQ(Assembler::kJSReturnSequenceLength,
191 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 190 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
192 #endif 191 #endif
193 } 192 }
194 } 193 }
195 194
196 195
197 void FastCodeGenerator::Apply(Expression::Context context, 196 void FastCodeGenerator::Apply(Expression::Context context, Register reg) {
198 Slot* slot, 197 switch (context) {
199 Register scratch) { 198 case Expression::kUninitialized:
199 UNREACHABLE();
200
201 case Expression::kEffect:
202 // Nothing to do.
203 break;
204
205 case Expression::kValue:
206 // Move value into place.
207 switch (location_) {
208 case kAccumulator:
209 if (!reg.is(result_register())) __ mov(result_register(), reg);
210 break;
211 case kStack:
212 __ push(reg);
213 break;
214 }
215 break;
216
217 case Expression::kTest:
218 // For simplicity we always test the accumulator register.
219 if (!reg.is(result_register())) __ mov(result_register(), reg);
220 DoTest(context);
221 break;
222
223 case Expression::kValueTest:
224 case Expression::kTestValue:
225 if (!reg.is(result_register())) __ mov(result_register(), reg);
226 switch (location_) {
227 case kAccumulator:
228 break;
229 case kStack:
230 __ push(result_register());
231 break;
232 }
233 DoTest(context);
234 break;
235 }
236 }
237
238
239 void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) {
200 switch (context) { 240 switch (context) {
201 case Expression::kUninitialized: 241 case Expression::kUninitialized:
202 UNREACHABLE(); 242 UNREACHABLE();
203 case Expression::kEffect: 243 case Expression::kEffect:
244 // Nothing to do.
204 break; 245 break;
205 case Expression::kValue: { 246 case Expression::kValue: {
206 MemOperand location = EmitSlotSearch(slot, scratch); 247 MemOperand slot_operand = EmitSlotSearch(slot, result_register());
207 __ push(location); 248 switch (location_) {
249 case kAccumulator:
250 __ mov(result_register(), slot_operand);
251 break;
252 case kStack:
253 // Memory operands can be pushed directly.
254 __ push(slot_operand);
255 break;
256 }
208 break; 257 break;
209 } 258 }
259
210 case Expression::kTest: 260 case Expression::kTest:
261 // For simplicity we always test the accumulator register.
262 Move(result_register(), slot);
263 DoTest(context);
264 break;
265
211 case Expression::kValueTest: 266 case Expression::kValueTest:
212 case Expression::kTestValue: 267 case Expression::kTestValue:
213 Move(scratch, slot); 268 Move(result_register(), slot);
214 Apply(context, scratch); 269 switch (location_) {
270 case kAccumulator:
271 break;
272 case kStack:
273 __ push(result_register());
274 break;
275 }
276 DoTest(context);
215 break; 277 break;
216 } 278 }
217 } 279 }
218 280
219 281
220 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { 282 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
221 switch (context) { 283 switch (context) {
222 case Expression::kUninitialized: 284 case Expression::kUninitialized:
223 UNREACHABLE(); 285 UNREACHABLE();
224 case Expression::kEffect: 286 case Expression::kEffect:
287 // Nothing to do.
225 break; 288 break;
226 case Expression::kValue: 289 case Expression::kValue:
227 __ push(Immediate(lit->handle())); 290 switch (location_) {
291 case kAccumulator:
292 __ mov(result_register(), lit->handle());
293 break;
294 case kStack:
295 // Immediates can be pushed directly.
296 __ push(Immediate(lit->handle()));
297 break;
298 }
228 break; 299 break;
300
229 case Expression::kTest: 301 case Expression::kTest:
302 // For simplicity we always test the accumulator register.
303 __ mov(result_register(), lit->handle());
304 DoTest(context);
305 break;
306
230 case Expression::kValueTest: 307 case Expression::kValueTest:
231 case Expression::kTestValue: 308 case Expression::kTestValue:
232 __ mov(eax, lit->handle()); 309 __ mov(result_register(), lit->handle());
233 Apply(context, eax); 310 switch (location_) {
311 case kAccumulator:
312 break;
313 case kStack:
314 __ push(result_register());
315 break;
316 }
317 DoTest(context);
234 break; 318 break;
235 } 319 }
236 } 320 }
237 321
238 322
239 void FastCodeGenerator::ApplyTOS(Expression::Context context) { 323 void FastCodeGenerator::ApplyTOS(Expression::Context context) {
240 switch (context) { 324 switch (context) {
241 case Expression::kUninitialized: 325 case Expression::kUninitialized:
242 UNREACHABLE(); 326 UNREACHABLE();
327
243 case Expression::kEffect: 328 case Expression::kEffect:
244 __ Drop(1); 329 __ Drop(1);
245 break; 330 break;
331
246 case Expression::kValue: 332 case Expression::kValue:
333 switch (location_) {
334 case kAccumulator:
335 __ pop(result_register());
336 break;
337 case kStack:
338 break;
339 }
247 break; 340 break;
341
248 case Expression::kTest: 342 case Expression::kTest:
249 __ pop(eax); 343 // For simplicity we always test the accumulator register.
250 TestAndBranch(eax, true_label_, false_label_); 344 __ pop(result_register());
345 DoTest(context);
251 break; 346 break;
252 case Expression::kValueTest: { 347
253 Label discard; 348 case Expression::kValueTest:
254 __ mov(eax, Operand(esp, 0)); 349 case Expression::kTestValue:
255 TestAndBranch(eax, true_label_, &discard); 350 switch (location_) {
256 __ bind(&discard); 351 case kAccumulator:
257 __ Drop(1); 352 __ pop(result_register());
258 __ jmp(false_label_); 353 break;
354 case kStack:
355 __ mov(result_register(), Operand(esp, 0));
356 break;
357 }
358 DoTest(context);
259 break; 359 break;
260 }
261 case Expression::kTestValue: {
262 Label discard;
263 __ mov(eax, Operand(esp, 0));
264 TestAndBranch(eax, &discard, false_label_);
265 __ bind(&discard);
266 __ Drop(1);
267 __ jmp(true_label_);
268 }
269 } 360 }
270 } 361 }
271 362
272 363
273 void FastCodeGenerator::DropAndApply(int count, 364 void FastCodeGenerator::DropAndApply(int count,
274 Expression::Context context, 365 Expression::Context context,
275 Register reg) { 366 Register reg) {
276 ASSERT(count > 0); 367 ASSERT(count > 0);
277 ASSERT(!reg.is(esp)); 368 ASSERT(!reg.is(esp));
278 switch (context) { 369 switch (context) {
279 case Expression::kUninitialized: 370 case Expression::kUninitialized:
280 UNREACHABLE(); 371 UNREACHABLE();
372
281 case Expression::kEffect: 373 case Expression::kEffect:
282 __ Drop(count); 374 __ Drop(count);
283 break; 375 break;
284 case Expression::kValue: 376
285 if (count > 1) __ Drop(count - 1); 377 case Expression::kValue:
286 __ mov(Operand(esp, 0), reg); 378 switch (location_) {
287 break; 379 case kAccumulator:
288 case Expression::kTest: 380 __ Drop(count);
381 if (!reg.is(result_register())) __ mov(result_register(), reg);
382 break;
383 case kStack:
384 if (count > 1) __ Drop(count - 1);
385 __ mov(Operand(esp, 0), reg);
386 break;
387 }
388 break;
389
390 case Expression::kTest:
391 // For simplicity we always test the accumulator register.
289 __ Drop(count); 392 __ Drop(count);
290 TestAndBranch(reg, true_label_, false_label_); 393 if (!reg.is(result_register())) __ mov(result_register(), reg);
291 break; 394 DoTest(context);
292 case Expression::kValueTest: { 395 break;
293 Label discard; 396
294 if (count > 1) __ Drop(count - 1); 397 case Expression::kValueTest:
295 __ mov(Operand(esp, 0), reg); 398 case Expression::kTestValue:
296 TestAndBranch(reg, true_label_, &discard); 399 switch (location_) {
400 case kAccumulator:
401 __ Drop(count);
402 if (!reg.is(result_register())) __ mov(result_register(), reg);
403 break;
404 case kStack:
405 if (count > 1) __ Drop(count - 1);
406 __ mov(result_register(), reg);
407 __ mov(Operand(esp, 0), result_register());
408 break;
409 }
410 DoTest(context);
411 break;
412 }
413 }
414
415
416 void FastCodeGenerator::Apply(Expression::Context context,
417 Label* materialize_true,
418 Label* materialize_false) {
419 switch (context) {
420 case Expression::kUninitialized:
421
422 case Expression::kEffect:
423 ASSERT_EQ(materialize_true, materialize_false);
424 __ bind(materialize_true);
425 break;
426
427 case Expression::kValue: {
428 Label done;
429 switch (location_) {
430 case kAccumulator:
431 __ bind(materialize_true);
432 __ mov(result_register(), Factory::true_value());
433 __ jmp(&done);
434 __ bind(materialize_false);
435 __ mov(result_register(), Factory::false_value());
436 break;
437 case kStack:
438 __ bind(materialize_true);
439 __ push(Immediate(Factory::true_value()));
440 __ jmp(&done);
441 __ bind(materialize_false);
442 __ push(Immediate(Factory::false_value()));
443 break;
444 }
445 __ bind(&done);
446 break;
447 }
448
449 case Expression::kTest:
450 break;
451
452 case Expression::kValueTest:
453 __ bind(materialize_true);
454 switch (location_) {
455 case kAccumulator:
456 __ mov(result_register(), Factory::true_value());
457 break;
458 case kStack:
459 __ push(Immediate(Factory::true_value()));
460 break;
461 }
462 __ jmp(true_label_);
463 break;
464
465 case Expression::kTestValue:
466 __ bind(materialize_false);
467 switch (location_) {
468 case kAccumulator:
469 __ mov(result_register(), Factory::false_value());
470 break;
471 case kStack:
472 __ push(Immediate(Factory::false_value()));
473 break;
474 }
475 __ jmp(false_label_);
476 break;
477 }
478 }
479
480
481 void FastCodeGenerator::DoTest(Expression::Context context) {
482 // The value to test is in the accumulator. If the value might be needed
483 // on the stack (value/test and test/value contexts with a stack location
484 // desired), then the value is already duplicated on the stack.
485 ASSERT_NE(NULL, true_label_);
486 ASSERT_NE(NULL, false_label_);
487
488 // In value/test and test/value expression contexts with stack as the
489 // desired location, there is already an extra value on the stack. Use a
490 // label to discard it if unneeded.
491 Label discard;
492 Label* if_true = true_label_;
493 Label* if_false = false_label_;
494 switch (context) {
495 case Expression::kUninitialized:
496 case Expression::kEffect:
497 case Expression::kValue:
498 UNREACHABLE();
499 case Expression::kTest:
500 break;
501 case Expression::kValueTest:
502 switch (location_) {
503 case kAccumulator:
504 break;
505 case kStack:
506 if_false = &discard;
507 break;
508 }
509 break;
510 case Expression::kTestValue:
511 switch (location_) {
512 case kAccumulator:
513 break;
514 case kStack:
515 if_true = &discard;
516 break;
517 }
518 break;
519 }
520
521 // Emit the inlined tests assumed by the stub.
522 __ cmp(result_register(), Factory::undefined_value());
523 __ j(equal, if_false);
524 __ cmp(result_register(), Factory::true_value());
525 __ j(equal, if_true);
526 __ cmp(result_register(), Factory::false_value());
527 __ j(equal, if_false);
528 ASSERT_EQ(0, kSmiTag);
529 __ test(result_register(), Operand(result_register()));
530 __ j(zero, if_false);
531 __ test(result_register(), Immediate(kSmiTagMask));
532 __ j(zero, if_true);
533
534 // Save a copy of the value if it may be needed and isn't already saved.
535 switch (context) {
536 case Expression::kUninitialized:
537 case Expression::kEffect:
538 case Expression::kValue:
539 UNREACHABLE();
540 case Expression::kTest:
541 break;
542 case Expression::kValueTest:
543 switch (location_) {
544 case kAccumulator:
545 __ push(result_register());
546 break;
547 case kStack:
548 break;
549 }
550 break;
551 case Expression::kTestValue:
552 switch (location_) {
553 case kAccumulator:
554 __ push(result_register());
555 break;
556 case kStack:
557 break;
558 }
559 break;
560 }
561
562 // Call the ToBoolean stub for all other cases.
563 ToBooleanStub stub;
564 __ push(result_register());
565 __ CallStub(&stub);
566 __ test(eax, Operand(eax));
567
568 // The stub returns nonzero for true. Complete based on the context.
569 switch (context) {
570 case Expression::kUninitialized:
571 case Expression::kEffect:
572 case Expression::kValue:
573 UNREACHABLE();
574
575 case Expression::kTest:
576 __ j(not_zero, true_label_);
577 __ jmp(false_label_);
578 break;
579
580 case Expression::kValueTest:
581 switch (location_) {
582 case kAccumulator:
583 __ j(zero, &discard);
584 __ pop(result_register());
585 __ jmp(true_label_);
586 break;
587 case kStack:
588 __ j(not_zero, true_label_);
589 break;
590 }
297 __ bind(&discard); 591 __ bind(&discard);
298 __ Drop(1); 592 __ Drop(1);
299 __ jmp(false_label_); 593 __ jmp(false_label_);
300 break; 594 break;
301 } 595
302 case Expression::kTestValue: { 596 case Expression::kTestValue:
303 Label discard; 597 switch (location_) {
304 if (count > 1) __ Drop(count - 1); 598 case kAccumulator:
305 __ mov(Operand(esp, 0), reg); 599 __ j(not_zero, &discard);
306 TestAndBranch(reg, &discard, false_label_); 600 __ pop(result_register());
601 __ jmp(false_label_);
602 break;
603 case kStack:
604 __ j(zero, false_label_);
605 break;
606 }
307 __ bind(&discard); 607 __ bind(&discard);
308 __ Drop(1); 608 __ Drop(1);
309 __ jmp(true_label_); 609 __ jmp(true_label_);
310 break; 610 break;
311 }
312 } 611 }
313 } 612 }
314 613
315 614
316 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 615 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
317 switch (slot->type()) { 616 switch (slot->type()) {
318 case Slot::PARAMETER: 617 case Slot::PARAMETER:
319 case Slot::LOCAL: 618 case Slot::LOCAL:
320 return Operand(ebp, SlotOffset(slot)); 619 return Operand(ebp, SlotOffset(slot));
321 case Slot::CONTEXT: { 620 case Slot::CONTEXT: {
(...skipping 25 matching lines...) Expand all
347 MemOperand location = EmitSlotSearch(dst, scratch1); 646 MemOperand location = EmitSlotSearch(dst, scratch1);
348 __ mov(location, src); 647 __ mov(location, src);
349 // Emit the write barrier code if the location is in the heap. 648 // Emit the write barrier code if the location is in the heap.
350 if (dst->type() == Slot::CONTEXT) { 649 if (dst->type() == Slot::CONTEXT) {
351 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 650 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
352 __ RecordWrite(scratch1, offset, src, scratch2); 651 __ RecordWrite(scratch1, offset, src, scratch2);
353 } 652 }
354 } 653 }
355 654
356 655
357 void FastCodeGenerator::TestAndBranch(Register source,
358 Label* true_label,
359 Label* false_label) {
360 ASSERT_NE(NULL, true_label);
361 ASSERT_NE(NULL, false_label);
362 // Use the shared ToBoolean stub to compile the value in the register into
363 // control flow to the code generator's true and false labels. Perform
364 // the fast checks assumed by the stub.
365 __ cmp(source, Factory::undefined_value()); // The undefined value is false.
366 __ j(equal, false_label);
367 __ cmp(source, Factory::true_value()); // True is true.
368 __ j(equal, true_label);
369 __ cmp(source, Factory::false_value()); // False is false.
370 __ j(equal, false_label);
371 ASSERT_EQ(0, kSmiTag);
372 __ test(source, Operand(source)); // The smi zero is false.
373 __ j(zero, false_label);
374 __ test(source, Immediate(kSmiTagMask)); // All other smis are true.
375 __ j(zero, true_label);
376
377 // Call the stub for all other cases.
378 __ push(source);
379 ToBooleanStub stub;
380 __ CallStub(&stub);
381 __ test(eax, Operand(eax)); // The stub returns nonzero for true.
382 __ j(not_zero, true_label);
383 __ jmp(false_label);
384 }
385
386
387 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { 656 void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
388 Comment cmnt(masm_, "[ Declaration"); 657 Comment cmnt(masm_, "[ Declaration");
389 Variable* var = decl->proxy()->var(); 658 Variable* var = decl->proxy()->var();
390 ASSERT(var != NULL); // Must have been resolved. 659 ASSERT(var != NULL); // Must have been resolved.
391 Slot* slot = var->slot(); 660 Slot* slot = var->slot();
392 Property* prop = var->AsProperty(); 661 Property* prop = var->AsProperty();
393 662
394 if (slot != NULL) { 663 if (slot != NULL) {
395 switch (slot->type()) { 664 switch (slot->type()) {
396 case Slot::PARAMETER: 665 case Slot::PARAMETER:
397 case Slot::LOCAL: 666 case Slot::LOCAL:
398 if (decl->mode() == Variable::CONST) { 667 if (decl->mode() == Variable::CONST) {
399 __ mov(Operand(ebp, SlotOffset(slot)), 668 __ mov(Operand(ebp, SlotOffset(slot)),
400 Immediate(Factory::the_hole_value())); 669 Immediate(Factory::the_hole_value()));
401 } else if (decl->fun() != NULL) { 670 } else if (decl->fun() != NULL) {
402 Visit(decl->fun()); 671 VisitForValue(decl->fun(), kAccumulator);
403 __ pop(Operand(ebp, SlotOffset(slot))); 672 __ mov(Operand(ebp, SlotOffset(slot)), result_register());
404 } 673 }
405 break; 674 break;
406 675
407 case Slot::CONTEXT: 676 case Slot::CONTEXT:
408 // We bypass the general EmitSlotSearch because we know more about 677 // We bypass the general EmitSlotSearch because we know more about
409 // this specific context. 678 // this specific context.
410 679
411 // The variable in the decl always resides in the current context. 680 // The variable in the decl always resides in the current context.
412 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); 681 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
413 if (FLAG_debug_code) { 682 if (FLAG_debug_code) {
414 // Check if we have the correct context pointer. 683 // Check if we have the correct context pointer.
415 __ mov(ebx, 684 __ mov(ebx,
416 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); 685 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX));
417 __ cmp(ebx, Operand(esi)); 686 __ cmp(ebx, Operand(esi));
418 __ Check(equal, "Unexpected declaration in current context."); 687 __ Check(equal, "Unexpected declaration in current context.");
419 } 688 }
420 if (decl->mode() == Variable::CONST) { 689 if (decl->mode() == Variable::CONST) {
421 __ mov(eax, Immediate(Factory::the_hole_value())); 690 __ mov(eax, Immediate(Factory::the_hole_value()));
422 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax); 691 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax);
423 // No write barrier since the hole value is in old space. 692 // No write barrier since the hole value is in old space.
424 } else if (decl->fun() != NULL) { 693 } else if (decl->fun() != NULL) {
425 Visit(decl->fun()); 694 VisitForValue(decl->fun(), kAccumulator);
426 __ pop(eax); 695 __ mov(CodeGenerator::ContextOperand(esi, slot->index()),
427 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax); 696 result_register());
428 int offset = Context::SlotOffset(slot->index()); 697 int offset = Context::SlotOffset(slot->index());
429 __ RecordWrite(esi, offset, eax, ecx); 698 __ RecordWrite(esi, offset, result_register(), ecx);
430 } 699 }
431 break; 700 break;
432 701
433 case Slot::LOOKUP: { 702 case Slot::LOOKUP: {
434 __ push(esi); 703 __ push(esi);
435 __ push(Immediate(var->name())); 704 __ push(Immediate(var->name()));
436 // Declaration nodes are always introduced in one of two modes. 705 // Declaration nodes are always introduced in one of two modes.
437 ASSERT(decl->mode() == Variable::VAR || 706 ASSERT(decl->mode() == Variable::VAR ||
438 decl->mode() == Variable::CONST); 707 decl->mode() == Variable::CONST);
439 PropertyAttributes attr = 708 PropertyAttributes attr =
440 (decl->mode() == Variable::VAR) ? NONE : READ_ONLY; 709 (decl->mode() == Variable::VAR) ? NONE : READ_ONLY;
441 __ push(Immediate(Smi::FromInt(attr))); 710 __ push(Immediate(Smi::FromInt(attr)));
442 // Push initial value, if any. 711 // Push initial value, if any.
443 // Note: For variables we must not push an initial value (such as 712 // Note: For variables we must not push an initial value (such as
444 // 'undefined') because we may have a (legal) redeclaration and we 713 // 'undefined') because we may have a (legal) redeclaration and we
445 // must not destroy the current value. 714 // must not destroy the current value.
446 if (decl->mode() == Variable::CONST) { 715 if (decl->mode() == Variable::CONST) {
447 __ push(Immediate(Factory::the_hole_value())); 716 __ push(Immediate(Factory::the_hole_value()));
448 } else if (decl->fun() != NULL) { 717 } else if (decl->fun() != NULL) {
449 Visit(decl->fun()); 718 VisitForValue(decl->fun(), kStack);
450 } else { 719 } else {
451 __ push(Immediate(Smi::FromInt(0))); // No initial value! 720 __ push(Immediate(Smi::FromInt(0))); // No initial value!
452 } 721 }
453 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 722 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
454 break; 723 break;
455 } 724 }
456 } 725 }
457 726
458 } else if (prop != NULL) { 727 } else if (prop != NULL) {
459 if (decl->fun() != NULL || decl->mode() == Variable::CONST) { 728 if (decl->fun() != NULL || decl->mode() == Variable::CONST) {
460 // We are declaring a function or constant that rewrites to a 729 // We are declaring a function or constant that rewrites to a
461 // property. Use (keyed) IC to set the initial value. 730 // property. Use (keyed) IC to set the initial value.
462 ASSERT_EQ(Expression::kValue, prop->obj()->context()); 731 VisitForValue(prop->obj(), kStack);
463 Visit(prop->obj()); 732 VisitForValue(prop->key(), kStack);
464 ASSERT_EQ(Expression::kValue, prop->key()->context());
465 Visit(prop->key());
466 733
467 if (decl->fun() != NULL) { 734 if (decl->fun() != NULL) {
468 ASSERT_EQ(Expression::kValue, decl->fun()->context()); 735 VisitForValue(decl->fun(), kAccumulator);
469 Visit(decl->fun());
470 __ pop(eax);
471 } else { 736 } else {
472 __ Set(eax, Immediate(Factory::the_hole_value())); 737 __ mov(result_register(), Factory::the_hole_value());
473 } 738 }
474 739
475 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 740 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
476 __ call(ic, RelocInfo::CODE_TARGET); 741 __ call(ic, RelocInfo::CODE_TARGET);
477 // Absence of a test eax instruction following the call 742 // Absence of a test eax instruction following the call
478 // indicates that none of the load was inlined. 743 // indicates that none of the load was inlined.
744 __ nop();
479 745
480 // Value in eax is ignored (declarations are statements). Receiver 746 // Value in eax is ignored (declarations are statements). Receiver
481 // and key on stack are discarded. 747 // and key on stack are discarded.
482 __ Drop(2); 748 __ Drop(2);
483 } 749 }
484 } 750 }
485 } 751 }
486 752
487 753
488 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 754 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 } 814 }
549 case Slot::CONTEXT: { 815 case Slot::CONTEXT: {
550 Comment cmnt(masm_, "Context slot"); 816 Comment cmnt(masm_, "Context slot");
551 break; 817 break;
552 } 818 }
553 case Slot::LOOKUP: 819 case Slot::LOOKUP:
554 UNIMPLEMENTED(); 820 UNIMPLEMENTED();
555 break; 821 break;
556 } 822 }
557 } 823 }
558 Apply(context, slot, eax); 824 Apply(context, slot);
559 } else { 825 } else {
560 Comment cmnt(masm_, "Variable rewritten to property"); 826 Comment cmnt(masm_, "Variable rewritten to property");
561 // A variable has been rewritten into an explicit access to an object 827 // A variable has been rewritten into an explicit access to an object
562 // property. 828 // property.
563 Property* property = rewrite->AsProperty(); 829 Property* property = rewrite->AsProperty();
564 ASSERT_NOT_NULL(property); 830 ASSERT_NOT_NULL(property);
565 831
566 // The only property expressions that can occur are of the form 832 // The only property expressions that can occur are of the form
567 // "slot[literal]". 833 // "slot[literal]".
568 834
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 894 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
629 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); 895 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
630 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 896 __ push(Immediate(Smi::FromInt(expr->literal_index())));
631 __ push(Immediate(expr->constant_properties())); 897 __ push(Immediate(expr->constant_properties()));
632 if (expr->depth() > 1) { 898 if (expr->depth() > 1) {
633 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); 899 __ CallRuntime(Runtime::kCreateObjectLiteral, 3);
634 } else { 900 } else {
635 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); 901 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
636 } 902 }
637 903
638 // If result_saved == true: The result is saved on top of the 904 // If result_saved is true the result is on top of the stack. If
639 // stack and in eax. 905 // result_saved is false the result is in eax.
640 // If result_saved == false: The result not on the stack, just in eax.
641 bool result_saved = false; 906 bool result_saved = false;
642 907
643 for (int i = 0; i < expr->properties()->length(); i++) { 908 for (int i = 0; i < expr->properties()->length(); i++) {
644 ObjectLiteral::Property* property = expr->properties()->at(i); 909 ObjectLiteral::Property* property = expr->properties()->at(i);
645 if (property->IsCompileTimeValue()) continue; 910 if (property->IsCompileTimeValue()) continue;
646 911
647 Literal* key = property->key(); 912 Literal* key = property->key();
648 Expression* value = property->value(); 913 Expression* value = property->value();
649 if (!result_saved) { 914 if (!result_saved) {
650 __ push(eax); // Save result on the stack 915 __ push(eax); // Save result on the stack
651 result_saved = true; 916 result_saved = true;
652 } 917 }
653 switch (property->kind()) { 918 switch (property->kind()) {
654 case ObjectLiteral::Property::MATERIALIZED_LITERAL: // Fall through. 919 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
655 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 920 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
921 // Fall through.
656 case ObjectLiteral::Property::COMPUTED: 922 case ObjectLiteral::Property::COMPUTED:
657 if (key->handle()->IsSymbol()) { 923 if (key->handle()->IsSymbol()) {
658 Visit(value); 924 VisitForValue(value, kAccumulator);
659 ASSERT_EQ(Expression::kValue, value->context());
660 __ pop(eax);
661 __ mov(ecx, Immediate(key->handle())); 925 __ mov(ecx, Immediate(key->handle()));
662 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 926 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
663 __ call(ic, RelocInfo::CODE_TARGET); 927 __ call(ic, RelocInfo::CODE_TARGET);
928 __ nop();
664 // StoreIC leaves the receiver on the stack. 929 // StoreIC leaves the receiver on the stack.
665 __ mov(eax, Operand(esp, 0)); // Restore result into eax.
666 break; 930 break;
667 } 931 }
668 // Fall through. 932 // Fall through.
669 case ObjectLiteral::Property::PROTOTYPE: 933 case ObjectLiteral::Property::PROTOTYPE:
670 __ push(eax); 934 __ push(Operand(esp, 0)); // Duplicate receiver.
671 Visit(key); 935 VisitForValue(key, kStack);
672 ASSERT_EQ(Expression::kValue, key->context()); 936 VisitForValue(value, kStack);
673 Visit(value);
674 ASSERT_EQ(Expression::kValue, value->context());
675 __ CallRuntime(Runtime::kSetProperty, 3); 937 __ CallRuntime(Runtime::kSetProperty, 3);
676 __ mov(eax, Operand(esp, 0)); // Restore result into eax.
677 break; 938 break;
678 case ObjectLiteral::Property::SETTER: 939 case ObjectLiteral::Property::SETTER:
679 case ObjectLiteral::Property::GETTER: 940 case ObjectLiteral::Property::GETTER:
680 __ push(eax); 941 __ push(Operand(esp, 0)); // Duplicate receiver.
681 Visit(key); 942 VisitForValue(key, kStack);
682 ASSERT_EQ(Expression::kValue, key->context());
683 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? 943 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
684 Smi::FromInt(1) : 944 Smi::FromInt(1) :
685 Smi::FromInt(0))); 945 Smi::FromInt(0)));
686 Visit(value); 946 VisitForValue(value, kStack);
687 ASSERT_EQ(Expression::kValue, value->context());
688 __ CallRuntime(Runtime::kDefineAccessor, 4); 947 __ CallRuntime(Runtime::kDefineAccessor, 4);
689 __ mov(eax, Operand(esp, 0)); // Restore result into eax.
690 break; 948 break;
691 default: UNREACHABLE(); 949 default: UNREACHABLE();
692 } 950 }
693 } 951 }
694 switch (expr->context()) { 952
695 case Expression::kUninitialized: 953 if (result_saved) {
696 UNREACHABLE(); 954 ApplyTOS(expr->context());
697 case Expression::kEffect: 955 } else {
698 if (result_saved) __ Drop(1); 956 Apply(expr->context(), eax);
699 break;
700 case Expression::kValue:
701 if (!result_saved) __ push(eax);
702 break;
703 case Expression::kTest:
704 if (result_saved) __ pop(eax);
705 TestAndBranch(eax, true_label_, false_label_);
706 break;
707 case Expression::kValueTest: {
708 Label discard;
709 if (!result_saved) __ push(eax);
710 TestAndBranch(eax, true_label_, &discard);
711 __ bind(&discard);
712 __ Drop(1);
713 __ jmp(false_label_);
714 break;
715 }
716 case Expression::kTestValue: {
717 Label discard;
718 if (!result_saved) __ push(eax);
719 TestAndBranch(eax, &discard, false_label_);
720 __ bind(&discard);
721 __ Drop(1);
722 __ jmp(true_label_);
723 break;
724 }
725 } 957 }
726 } 958 }
727 959
728 960
729 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 961 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
730 Comment cmnt(masm_, "[ ArrayLiteral"); 962 Comment cmnt(masm_, "[ ArrayLiteral");
731 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 963 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
732 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); 964 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
733 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 965 __ push(Immediate(Smi::FromInt(expr->literal_index())));
734 __ push(Immediate(expr->constant_elements())); 966 __ push(Immediate(expr->constant_elements()));
(...skipping 14 matching lines...) Expand all
749 // is already set in the cloned array. 981 // is already set in the cloned array.
750 if (subexpr->AsLiteral() != NULL || 982 if (subexpr->AsLiteral() != NULL ||
751 CompileTimeValue::IsCompileTimeValue(subexpr)) { 983 CompileTimeValue::IsCompileTimeValue(subexpr)) {
752 continue; 984 continue;
753 } 985 }
754 986
755 if (!result_saved) { 987 if (!result_saved) {
756 __ push(eax); 988 __ push(eax);
757 result_saved = true; 989 result_saved = true;
758 } 990 }
759 Visit(subexpr); 991 VisitForValue(subexpr, kAccumulator);
760 ASSERT_EQ(Expression::kValue, subexpr->context());
761 992
762 // Store the subexpression value in the array's elements. 993 // Store the subexpression value in the array's elements.
763 __ pop(eax); // Subexpression value.
764 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. 994 __ mov(ebx, Operand(esp, 0)); // Copy of array literal.
765 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); 995 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
766 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 996 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
767 __ mov(FieldOperand(ebx, offset), eax); 997 __ mov(FieldOperand(ebx, offset), result_register());
768 998
769 // Update the write barrier for the array store. 999 // Update the write barrier for the array store.
770 __ RecordWrite(ebx, offset, eax, ecx); 1000 __ RecordWrite(ebx, offset, result_register(), ecx);
771 } 1001 }
772 1002
773 switch (expr->context()) { 1003 if (result_saved) {
774 case Expression::kUninitialized: 1004 ApplyTOS(expr->context());
775 UNREACHABLE(); 1005 } else {
776 case Expression::kEffect: 1006 Apply(expr->context(), eax);
777 if (result_saved) __ Drop(1);
778 break;
779 case Expression::kValue:
780 if (!result_saved) __ push(eax);
781 break;
782 case Expression::kTest:
783 if (result_saved) __ pop(eax);
784 TestAndBranch(eax, true_label_, false_label_);
785 break;
786 case Expression::kValueTest: {
787 Label discard;
788 if (!result_saved) __ push(eax);
789 TestAndBranch(eax, true_label_, &discard);
790 __ bind(&discard);
791 __ Drop(1);
792 __ jmp(false_label_);
793 break;
794 }
795 case Expression::kTestValue: {
796 Label discard;
797 if (!result_saved) __ push(eax);
798 TestAndBranch(eax, &discard, false_label_);
799 __ bind(&discard);
800 __ Drop(1);
801 __ jmp(true_label_);
802 break;
803 }
804 } 1007 }
805 } 1008 }
806 1009
807 1010
808 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, 1011 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
809 Expression::Context context) {
810 SetSourcePosition(prop->position()); 1012 SetSourcePosition(prop->position());
811 Literal* key = prop->key()->AsLiteral(); 1013 Literal* key = prop->key()->AsLiteral();
812 __ mov(ecx, Immediate(key->handle())); 1014 __ mov(ecx, Immediate(key->handle()));
813 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1015 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
814 __ call(ic, RelocInfo::CODE_TARGET); 1016 __ call(ic, RelocInfo::CODE_TARGET);
815 Apply(context, eax); 1017 __ nop();
816 } 1018 }
817 1019
818 1020
819 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, 1021 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
820 Expression::Context context) {
821 SetSourcePosition(prop->position()); 1022 SetSourcePosition(prop->position());
822 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1023 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
823 __ call(ic, RelocInfo::CODE_TARGET); 1024 __ call(ic, RelocInfo::CODE_TARGET);
824 Apply(context, eax); 1025 __ nop();
825 } 1026 }
826 1027
827 1028
828 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, 1029 void FastCodeGenerator::EmitBinaryOp(Token::Value op,
829 Expression::Context context) { 1030 Expression::Context context) {
1031 __ push(result_register());
830 GenericBinaryOpStub stub(op, 1032 GenericBinaryOpStub stub(op,
831 NO_OVERWRITE, 1033 NO_OVERWRITE,
832 NO_GENERIC_BINARY_FLAGS); 1034 NO_GENERIC_BINARY_FLAGS);
833 __ CallStub(&stub); 1035 __ CallStub(&stub);
834 Apply(context, eax); 1036 Apply(context, eax);
835 } 1037 }
836 1038
837 1039
838 void FastCodeGenerator::EmitVariableAssignment(Variable* var, 1040 void FastCodeGenerator::EmitVariableAssignment(Variable* var,
839 Expression::Context context) { 1041 Expression::Context context) {
840 ASSERT(var != NULL); 1042 ASSERT(var != NULL);
841 ASSERT(var->is_global() || var->slot() != NULL); 1043 ASSERT(var->is_global() || var->slot() != NULL);
842 if (var->is_global()) { 1044 if (var->is_global()) {
843 // Assignment to a global variable. Use inline caching for the 1045 // Assignment to a global variable. Use inline caching for the
844 // assignment. Right-hand-side value is passed in eax, variable name in 1046 // assignment. Right-hand-side value is passed in eax, variable name in
845 // ecx, and the global object on the stack. 1047 // ecx, and the global object on the stack.
846 __ pop(eax);
847 __ mov(ecx, var->name()); 1048 __ mov(ecx, var->name());
848 __ push(CodeGenerator::GlobalObject()); 1049 __ push(CodeGenerator::GlobalObject());
849 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1050 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
850 __ call(ic, RelocInfo::CODE_TARGET); 1051 __ call(ic, RelocInfo::CODE_TARGET);
1052 __ nop();
851 // Overwrite the receiver on the stack with the result if needed. 1053 // Overwrite the receiver on the stack with the result if needed.
852 DropAndApply(1, context, eax); 1054 DropAndApply(1, context, eax);
853 1055
854 } else if (var->slot() != NULL) { 1056 } else if (var->slot() != NULL) {
855 Slot* slot = var->slot(); 1057 Slot* slot = var->slot();
856 switch (slot->type()) { 1058 switch (slot->type()) {
857 case Slot::LOCAL: 1059 case Slot::LOCAL:
858 case Slot::PARAMETER: { 1060 case Slot::PARAMETER:
859 Operand target = Operand(ebp, SlotOffset(slot)); 1061 __ mov(Operand(ebp, SlotOffset(slot)), result_register());
860 switch (context) { 1062 break;
861 case Expression::kUninitialized: 1063
862 UNREACHABLE(); 1064 case Slot::CONTEXT: {
863 case Expression::kEffect: 1065 MemOperand target = EmitSlotSearch(slot, ecx);
864 // Perform assignment and discard value. 1066 __ mov(target, result_register());
865 __ pop(target); 1067
866 break; 1068 // RecordWrite may destroy all its register arguments.
867 case Expression::kValue: 1069 __ mov(edx, result_register());
868 // Perform assignment and preserve value. 1070 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
869 __ mov(eax, Operand(esp, 0)); 1071 __ RecordWrite(ecx, offset, edx, ebx);
870 __ mov(target, eax);
871 break;
872 case Expression::kTest:
873 // Perform assignment and test (and discard) value.
874 __ pop(eax);
875 __ mov(target, eax);
876 TestAndBranch(eax, true_label_, false_label_);
877 break;
878 case Expression::kValueTest: {
879 Label discard;
880 __ mov(eax, Operand(esp, 0));
881 __ mov(target, eax);
882 TestAndBranch(eax, true_label_, &discard);
883 __ bind(&discard);
884 __ Drop(1);
885 __ jmp(false_label_);
886 break;
887 }
888 case Expression::kTestValue: {
889 Label discard;
890 __ mov(eax, Operand(esp, 0));
891 __ mov(target, eax);
892 TestAndBranch(eax, &discard, false_label_);
893 __ bind(&discard);
894 __ Drop(1);
895 __ jmp(true_label_);
896 break;
897 }
898 }
899 break; 1072 break;
900 } 1073 }
901 1074
902 case Slot::CONTEXT: {
903 MemOperand target = EmitSlotSearch(slot, ecx);
904 __ pop(eax);
905 __ mov(target, eax);
906
907 // RecordWrite may destroy all its register arguments.
908 if (context == Expression::kValue) {
909 __ push(eax);
910 } else if (context != Expression::kEffect) {
911 __ mov(edx, eax);
912 }
913 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
914 __ RecordWrite(ecx, offset, eax, ebx);
915 if (context != Expression::kEffect && context != Expression::kValue) {
916 Apply(context, edx);
917 }
918 break;
919 }
920
921 case Slot::LOOKUP: 1075 case Slot::LOOKUP:
922 UNREACHABLE(); 1076 UNREACHABLE();
923 break; 1077 break;
924 } 1078 }
1079 Apply(context, result_register());
1080
925 } else { 1081 } else {
926 // Variables rewritten as properties are not treated as variables in 1082 // Variables rewritten as properties are not treated as variables in
927 // assignments. 1083 // assignments.
928 UNREACHABLE(); 1084 UNREACHABLE();
929 } 1085 }
930 } 1086 }
931 1087
932 1088
933 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1089 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
934 // Assignment to a property, using a named store IC. 1090 // Assignment to a property, using a named store IC.
935 Property* prop = expr->target()->AsProperty(); 1091 Property* prop = expr->target()->AsProperty();
936 ASSERT(prop != NULL); 1092 ASSERT(prop != NULL);
937 ASSERT(prop->key()->AsLiteral() != NULL); 1093 ASSERT(prop->key()->AsLiteral() != NULL);
938 1094
939 // If the assignment starts a block of assignments to the same object, 1095 // If the assignment starts a block of assignments to the same object,
940 // change to slow case to avoid the quadratic behavior of repeatedly 1096 // change to slow case to avoid the quadratic behavior of repeatedly
941 // adding fast properties. 1097 // adding fast properties.
942 if (expr->starts_initialization_block()) { 1098 if (expr->starts_initialization_block()) {
943 __ push(Operand(esp, kPointerSize)); // Receiver is under value. 1099 __ push(result_register());
1100 __ push(Operand(esp, kPointerSize)); // Receiver is now under value.
944 __ CallRuntime(Runtime::kToSlowProperties, 1); 1101 __ CallRuntime(Runtime::kToSlowProperties, 1);
1102 __ pop(result_register());
945 } 1103 }
946 1104
947 __ pop(eax); 1105 // Record source code position before IC call.
1106 SetSourcePosition(expr->position());
948 __ mov(ecx, prop->key()->AsLiteral()->handle()); 1107 __ mov(ecx, prop->key()->AsLiteral()->handle());
949 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1108 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
950 __ call(ic, RelocInfo::CODE_TARGET); 1109 __ call(ic, RelocInfo::CODE_TARGET);
1110 __ nop();
951 1111
952 // If the assignment ends an initialization block, revert to fast case. 1112 // If the assignment ends an initialization block, revert to fast case.
953 if (expr->ends_initialization_block()) { 1113 if (expr->ends_initialization_block()) {
954 __ push(eax); // Result of assignment, saved even if not needed. 1114 __ push(eax); // Result of assignment, saved even if not needed.
955 __ push(Operand(esp, kPointerSize)); // Receiver is under value. 1115 __ push(Operand(esp, kPointerSize)); // Receiver is under value.
956 __ CallRuntime(Runtime::kToFastProperties, 1); 1116 __ CallRuntime(Runtime::kToFastProperties, 1);
957 __ pop(eax); 1117 __ pop(eax);
958 } 1118 }
959 1119
960 DropAndApply(1, expr->context(), eax); 1120 DropAndApply(1, expr->context(), eax);
961 } 1121 }
962 1122
963 1123
964 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1124 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
965 // Assignment to a property, using a keyed store IC. 1125 // Assignment to a property, using a keyed store IC.
966 1126
967 // If the assignment starts a block of assignments to the same object, 1127 // If the assignment starts a block of assignments to the same object,
968 // change to slow case to avoid the quadratic behavior of repeatedly 1128 // change to slow case to avoid the quadratic behavior of repeatedly
969 // adding fast properties. 1129 // adding fast properties.
970 if (expr->starts_initialization_block()) { 1130 if (expr->starts_initialization_block()) {
971 // Reciever is under the key and value. 1131 __ push(result_register());
1132 // Receiver is now under the key and value.
972 __ push(Operand(esp, 2 * kPointerSize)); 1133 __ push(Operand(esp, 2 * kPointerSize));
973 __ CallRuntime(Runtime::kToSlowProperties, 1); 1134 __ CallRuntime(Runtime::kToSlowProperties, 1);
1135 __ pop(result_register());
974 } 1136 }
975 1137
976 __ pop(eax); 1138 // Record source code position before IC call.
1139 SetSourcePosition(expr->position());
977 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1140 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
978 __ call(ic, RelocInfo::CODE_TARGET); 1141 __ call(ic, RelocInfo::CODE_TARGET);
979 // This nop signals to the IC that there is no inlined code at the call 1142 // This nop signals to the IC that there is no inlined code at the call
980 // site for it to patch. 1143 // site for it to patch.
981 __ nop(); 1144 __ nop();
982 1145
983 // If the assignment ends an initialization block, revert to fast case. 1146 // If the assignment ends an initialization block, revert to fast case.
984 if (expr->ends_initialization_block()) { 1147 if (expr->ends_initialization_block()) {
985 __ push(eax); // Result of assignment, saved even if not needed. 1148 __ push(eax); // Result of assignment, saved even if not needed.
986 // Reciever is under the key and value. 1149 // Receiver is under the key and value.
987 __ push(Operand(esp, 2 * kPointerSize)); 1150 __ push(Operand(esp, 2 * kPointerSize));
988 __ CallRuntime(Runtime::kToFastProperties, 1); 1151 __ CallRuntime(Runtime::kToFastProperties, 1);
989 __ pop(eax); 1152 __ pop(eax);
990 } 1153 }
991 1154
992 // Receiver and key are still on stack. 1155 // Receiver and key are still on stack.
993 DropAndApply(2, expr->context(), eax); 1156 DropAndApply(2, expr->context(), eax);
994 } 1157 }
995 1158
996 1159
997 void FastCodeGenerator::VisitProperty(Property* expr) { 1160 void FastCodeGenerator::VisitProperty(Property* expr) {
998 Comment cmnt(masm_, "[ Property"); 1161 Comment cmnt(masm_, "[ Property");
999 Expression* key = expr->key(); 1162 Expression* key = expr->key();
1000 1163
1001 // Record the source position for the property load.
1002 SetSourcePosition(expr->position());
1003
1004 // Evaluate the receiver. 1164 // Evaluate the receiver.
1005 Visit(expr->obj()); 1165 VisitForValue(expr->obj(), kStack);
1006 1166
1007 if (key->IsPropertyName()) { 1167 if (key->IsPropertyName()) {
1008 // Do a named property load. The IC expects the property name in ecx 1168 EmitNamedPropertyLoad(expr);
1009 // and the receiver on the stack. 1169 // Drop receiver left on the stack by IC.
1010 __ mov(ecx, Immediate(key->AsLiteral()->handle()));
1011 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1012 __ call(ic, RelocInfo::CODE_TARGET);
1013 // By emitting a nop we make sure that we do not have a test eax
1014 // instruction after the call it is treated specially by the LoadIC code.
1015 __ nop();
1016 DropAndApply(1, expr->context(), eax); 1170 DropAndApply(1, expr->context(), eax);
1017 } else { 1171 } else {
1018 // Do a keyed property load. 1172 VisitForValue(expr->key(), kStack);
1019 Visit(expr->key()); 1173 EmitKeyedPropertyLoad(expr);
1020 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1174 // Drop key and receiver left on the stack by IC.
1021 __ call(ic, RelocInfo::CODE_TARGET);
1022 // By emitting a nop we make sure that we do not have a "test eax,..."
1023 // instruction after the call it is treated specially by the LoadIC code.
1024 __ nop();
1025 // Drop key left on the stack by IC.
1026 DropAndApply(2, expr->context(), eax); 1175 DropAndApply(2, expr->context(), eax);
1027 } 1176 }
1028 } 1177 }
1029 1178
1030 1179
1031 void FastCodeGenerator::EmitCallWithIC(Call* expr, 1180 void FastCodeGenerator::EmitCallWithIC(Call* expr,
1032 Handle<Object> name, 1181 Handle<Object> name,
1033 RelocInfo::Mode mode) { 1182 RelocInfo::Mode mode) {
1034 // Code common for calls using the IC. 1183 // Code common for calls using the IC.
1035 ZoneList<Expression*>* args = expr->arguments(); 1184 ZoneList<Expression*>* args = expr->arguments();
1036 int arg_count = args->length(); 1185 int arg_count = args->length();
1037 for (int i = 0; i < arg_count; i++) { 1186 for (int i = 0; i < arg_count; i++) {
1038 Visit(args->at(i)); 1187 VisitForValue(args->at(i), kStack);
1039 ASSERT_EQ(Expression::kValue, args->at(i)->context());
1040 } 1188 }
1041 __ Set(ecx, Immediate(name)); 1189 __ Set(ecx, Immediate(name));
1042 // Record source position of the IC call. 1190 // Record source position of the IC call.
1043 SetSourcePosition(expr->position()); 1191 SetSourcePosition(expr->position());
1044 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1192 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1045 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 1193 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
1046 __ call(ic, mode); 1194 __ call(ic, mode);
1047 // Restore context register. 1195 // Restore context register.
1048 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1196 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1049 Apply(expr->context(), eax); 1197 Apply(expr->context(), eax);
1050 } 1198 }
1051 1199
1052 1200
1053 void FastCodeGenerator::EmitCallWithStub(Call* expr) { 1201 void FastCodeGenerator::EmitCallWithStub(Call* expr) {
1054 // Code common for calls using the call stub. 1202 // Code common for calls using the call stub.
1055 ZoneList<Expression*>* args = expr->arguments(); 1203 ZoneList<Expression*>* args = expr->arguments();
1056 int arg_count = args->length(); 1204 int arg_count = args->length();
1057 for (int i = 0; i < arg_count; i++) { 1205 for (int i = 0; i < arg_count; i++) {
1058 Visit(args->at(i)); 1206 VisitForValue(args->at(i), kStack);
1059 } 1207 }
1060 // Record source position for debugger. 1208 // Record source position for debugger.
1061 SetSourcePosition(expr->position()); 1209 SetSourcePosition(expr->position());
1062 CallFunctionStub stub(arg_count, NOT_IN_LOOP); 1210 CallFunctionStub stub(arg_count, NOT_IN_LOOP);
1063 __ CallStub(&stub); 1211 __ CallStub(&stub);
1064 // Restore context register. 1212 // Restore context register.
1065 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1213 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1066 DropAndApply(1, expr->context(), eax); 1214 DropAndApply(1, expr->context(), eax);
1067 } 1215 }
1068 1216
(...skipping 13 matching lines...) Expand all
1082 } else if (var != NULL && var->slot() != NULL && 1230 } else if (var != NULL && var->slot() != NULL &&
1083 var->slot()->type() == Slot::LOOKUP) { 1231 var->slot()->type() == Slot::LOOKUP) {
1084 // Call to a lookup slot. 1232 // Call to a lookup slot.
1085 UNREACHABLE(); 1233 UNREACHABLE();
1086 } else if (fun->AsProperty() != NULL) { 1234 } else if (fun->AsProperty() != NULL) {
1087 // Call to an object property. 1235 // Call to an object property.
1088 Property* prop = fun->AsProperty(); 1236 Property* prop = fun->AsProperty();
1089 Literal* key = prop->key()->AsLiteral(); 1237 Literal* key = prop->key()->AsLiteral();
1090 if (key != NULL && key->handle()->IsSymbol()) { 1238 if (key != NULL && key->handle()->IsSymbol()) {
1091 // Call to a named property, use call IC. 1239 // Call to a named property, use call IC.
1092 Visit(prop->obj()); 1240 VisitForValue(prop->obj(), kStack);
1093 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1241 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1094 } else { 1242 } else {
1095 // Call to a keyed property, use keyed load IC followed by function 1243 // Call to a keyed property, use keyed load IC followed by function
1096 // call. 1244 // call.
1097 Visit(prop->obj()); 1245 VisitForValue(prop->obj(), kStack);
1098 Visit(prop->key()); 1246 VisitForValue(prop->key(), kStack);
1099 // Record source code position for IC call. 1247 // Record source code position for IC call.
1100 SetSourcePosition(prop->position()); 1248 SetSourcePosition(prop->position());
1101 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1249 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1102 __ call(ic, RelocInfo::CODE_TARGET); 1250 __ call(ic, RelocInfo::CODE_TARGET);
1103 // By emitting a nop we make sure that we do not have a "test eax,..." 1251 // By emitting a nop we make sure that we do not have a "test eax,..."
1104 // instruction after the call it is treated specially by the LoadIC code. 1252 // instruction after the call it is treated specially by the LoadIC code.
1105 __ nop(); 1253 __ nop();
1106 // Drop key left on the stack by IC. 1254 // Drop key left on the stack by IC.
1107 __ Drop(1); 1255 __ Drop(1);
1108 // Pop receiver. 1256 // Pop receiver.
(...skipping 12 matching lines...) Expand all
1121 } else { 1269 } else {
1122 // Call to some other expression. If the expression is an anonymous 1270 // Call to some other expression. If the expression is an anonymous
1123 // function literal not called in a loop, mark it as one that should 1271 // function literal not called in a loop, mark it as one that should
1124 // also use the fast code generator. 1272 // also use the fast code generator.
1125 FunctionLiteral* lit = fun->AsFunctionLiteral(); 1273 FunctionLiteral* lit = fun->AsFunctionLiteral();
1126 if (lit != NULL && 1274 if (lit != NULL &&
1127 lit->name()->Equals(Heap::empty_string()) && 1275 lit->name()->Equals(Heap::empty_string()) &&
1128 loop_depth() == 0) { 1276 loop_depth() == 0) {
1129 lit->set_try_fast_codegen(true); 1277 lit->set_try_fast_codegen(true);
1130 } 1278 }
1131 Visit(fun); 1279 VisitForValue(fun, kStack);
1132 // Load global receiver object. 1280 // Load global receiver object.
1133 __ mov(ebx, CodeGenerator::GlobalObject()); 1281 __ mov(ebx, CodeGenerator::GlobalObject());
1134 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 1282 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
1135 // Emit function call. 1283 // Emit function call.
1136 EmitCallWithStub(expr); 1284 EmitCallWithStub(expr);
1137 } 1285 }
1138 } 1286 }
1139 1287
1140 1288
1141 void FastCodeGenerator::VisitCallNew(CallNew* expr) { 1289 void FastCodeGenerator::VisitCallNew(CallNew* expr) {
1142 Comment cmnt(masm_, "[ CallNew"); 1290 Comment cmnt(masm_, "[ CallNew");
1143 // According to ECMA-262, section 11.2.2, page 44, the function 1291 // According to ECMA-262, section 11.2.2, page 44, the function
1144 // expression in new calls must be evaluated before the 1292 // expression in new calls must be evaluated before the
1145 // arguments. 1293 // arguments.
1146 // Push function on the stack. 1294 // Push function on the stack.
1147 Visit(expr->expression()); 1295 VisitForValue(expr->expression(), kStack);
1148 ASSERT_EQ(Expression::kValue, expr->expression()->context());
1149 1296
1150 // Push global object (receiver). 1297 // Push global object (receiver).
1151 __ push(CodeGenerator::GlobalObject()); 1298 __ push(CodeGenerator::GlobalObject());
1152 1299
1153 // Push the arguments ("left-to-right") on the stack. 1300 // Push the arguments ("left-to-right") on the stack.
1154 ZoneList<Expression*>* args = expr->arguments(); 1301 ZoneList<Expression*>* args = expr->arguments();
1155 int arg_count = args->length(); 1302 int arg_count = args->length();
1156 for (int i = 0; i < arg_count; i++) { 1303 for (int i = 0; i < arg_count; i++) {
1157 Visit(args->at(i)); 1304 VisitForValue(args->at(i), kStack);
1158 ASSERT_EQ(Expression::kValue, args->at(i)->context());
1159 // If location is value, it is already on the stack,
1160 // so nothing to do here.
1161 } 1305 }
1162 1306
1163 // Call the construct call builtin that handles allocation and 1307 // Call the construct call builtin that handles allocation and
1164 // constructor invocation. 1308 // constructor invocation.
1165 SetSourcePosition(expr->position()); 1309 SetSourcePosition(expr->position());
1166 1310
1167 // Load function, arg_count into edi and eax. 1311 // Load function, arg_count into edi and eax.
1168 __ Set(eax, Immediate(arg_count)); 1312 __ Set(eax, Immediate(arg_count));
1169 // Function is in esp[arg_count + 1]. 1313 // Function is in esp[arg_count + 1].
1170 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); 1314 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize));
(...skipping 12 matching lines...) Expand all
1183 1327
1184 if (expr->is_jsruntime()) { 1328 if (expr->is_jsruntime()) {
1185 // Prepare for calling JS runtime function. 1329 // Prepare for calling JS runtime function.
1186 __ mov(eax, CodeGenerator::GlobalObject()); 1330 __ mov(eax, CodeGenerator::GlobalObject());
1187 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); 1331 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
1188 } 1332 }
1189 1333
1190 // Push the arguments ("left-to-right"). 1334 // Push the arguments ("left-to-right").
1191 int arg_count = args->length(); 1335 int arg_count = args->length();
1192 for (int i = 0; i < arg_count; i++) { 1336 for (int i = 0; i < arg_count; i++) {
1193 Visit(args->at(i)); 1337 VisitForValue(args->at(i), kStack);
1194 ASSERT_EQ(Expression::kValue, args->at(i)->context());
1195 } 1338 }
1196 1339
1197 if (expr->is_jsruntime()) { 1340 if (expr->is_jsruntime()) {
1198 // Call the JS runtime function via a call IC. 1341 // Call the JS runtime function via a call IC.
1199 __ Set(ecx, Immediate(expr->name())); 1342 __ Set(ecx, Immediate(expr->name()));
1200 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1343 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1201 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 1344 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
1202 __ call(ic, RelocInfo::CODE_TARGET); 1345 __ call(ic, RelocInfo::CODE_TARGET);
1203 // Restore context register. 1346 // Restore context register.
1204 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1347 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1205 } else { 1348 } else {
1206 // Call the C runtime function. 1349 // Call the C runtime function.
1207 __ CallRuntime(expr->function(), arg_count); 1350 __ CallRuntime(expr->function(), arg_count);
1208 } 1351 }
1209 Apply(expr->context(), eax); 1352 Apply(expr->context(), eax);
1210 } 1353 }
1211 1354
1212 1355
1213 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 1356 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1214 switch (expr->op()) { 1357 switch (expr->op()) {
1215 case Token::VOID: { 1358 case Token::VOID: {
1216 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 1359 Comment cmnt(masm_, "[ UnaryOperation (VOID)");
1360 ASSERT_EQ(Expression::kEffect, expr->expression()->context());
1217 Visit(expr->expression()); 1361 Visit(expr->expression());
1218 ASSERT_EQ(Expression::kEffect, expr->expression()->context());
1219 switch (expr->context()) { 1362 switch (expr->context()) {
1220 case Expression::kUninitialized: 1363 case Expression::kUninitialized:
1221 UNREACHABLE(); 1364 UNREACHABLE();
1222 break; 1365 break;
1223 case Expression::kEffect: 1366 case Expression::kEffect:
1224 break; 1367 break;
1225 case Expression::kValue: 1368 case Expression::kValue:
1226 __ push(Immediate(Factory::undefined_value())); 1369 switch (location_) {
1370 case kAccumulator:
1371 __ mov(result_register(), Factory::undefined_value());
1372 break;
1373 case kStack:
1374 __ push(Immediate(Factory::undefined_value()));
1375 break;
1376 }
1227 break; 1377 break;
1228 case Expression::kTestValue: 1378 case Expression::kTestValue:
1229 // Value is false so it's needed. 1379 // Value is false so it's needed.
1230 __ push(Immediate(Factory::undefined_value())); 1380 switch (location_) {
1381 case kAccumulator:
1382 __ mov(result_register(), Factory::undefined_value());
1383 break;
1384 case kStack:
1385 __ push(Immediate(Factory::undefined_value()));
1386 break;
1387 }
1231 // Fall through. 1388 // Fall through.
1232 case Expression::kTest: 1389 case Expression::kTest:
1233 case Expression::kValueTest: 1390 case Expression::kValueTest:
1234 __ jmp(false_label_); 1391 __ jmp(false_label_);
1235 break; 1392 break;
1236 } 1393 }
1237 break; 1394 break;
1238 } 1395 }
1239 1396
1240 case Token::NOT: { 1397 case Token::NOT: {
1241 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 1398 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
1242 ASSERT_EQ(Expression::kTest, expr->expression()->context()); 1399 ASSERT_EQ(Expression::kTest, expr->expression()->context());
1243 1400
1244 Label push_true, push_false, done; 1401 Label materialize_true, materialize_false, done;
1402 // Initially assume a pure test context. Notice that the labels are
1403 // swapped.
1404 Label* if_true = false_label_;
1405 Label* if_false = true_label_;
1245 switch (expr->context()) { 1406 switch (expr->context()) {
1246 case Expression::kUninitialized: 1407 case Expression::kUninitialized:
1247 UNREACHABLE(); 1408 UNREACHABLE();
1248 break; 1409 break;
1249
1250 case Expression::kEffect: 1410 case Expression::kEffect:
1251 VisitForControl(expr->expression(), &done, &done); 1411 if_true = &done;
1252 __ bind(&done); 1412 if_false = &done;
1253 break; 1413 break;
1254
1255 case Expression::kValue: 1414 case Expression::kValue:
1256 VisitForControl(expr->expression(), &push_false, &push_true); 1415 if_true = &materialize_false;
1257 __ bind(&push_true); 1416 if_false = &materialize_true;
1258 __ push(Immediate(Factory::true_value()));
1259 __ jmp(&done);
1260 __ bind(&push_false);
1261 __ push(Immediate(Factory::false_value()));
1262 __ bind(&done);
1263 break; 1417 break;
1264
1265 case Expression::kTest: 1418 case Expression::kTest:
1266 VisitForControl(expr->expression(), false_label_, true_label_);
1267 break; 1419 break;
1268
1269 case Expression::kValueTest: 1420 case Expression::kValueTest:
1270 VisitForControl(expr->expression(), false_label_, &push_true); 1421 if_false = &materialize_true;
1271 __ bind(&push_true);
1272 __ push(Immediate(Factory::true_value()));
1273 __ jmp(true_label_);
1274 break; 1422 break;
1275
1276 case Expression::kTestValue: 1423 case Expression::kTestValue:
1277 VisitForControl(expr->expression(), &push_false, true_label_); 1424 if_true = &materialize_false;
1278 __ bind(&push_false);
1279 __ push(Immediate(Factory::false_value()));
1280 __ jmp(false_label_);
1281 break; 1425 break;
1282 } 1426 }
1427 VisitForControl(expr->expression(), if_true, if_false);
1428 Apply(expr->context(), if_false, if_true); // Labels swapped.
1283 break; 1429 break;
1284 } 1430 }
1285 1431
1286 case Token::TYPEOF: { 1432 case Token::TYPEOF: {
1287 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 1433 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
1288 ASSERT_EQ(Expression::kValue, expr->expression()->context()); 1434 ASSERT_EQ(Expression::kValue, expr->expression()->context());
1289 1435
1290 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 1436 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1291 if (proxy != NULL && 1437 if (proxy != NULL &&
1292 !proxy->var()->is_this() && 1438 !proxy->var()->is_this() &&
1293 proxy->var()->is_global()) { 1439 proxy->var()->is_global()) {
1294 Comment cmnt(masm_, "Global variable"); 1440 Comment cmnt(masm_, "Global variable");
1295 __ push(CodeGenerator::GlobalObject()); 1441 __ push(CodeGenerator::GlobalObject());
1296 __ mov(ecx, Immediate(proxy->name())); 1442 __ mov(ecx, Immediate(proxy->name()));
1297 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1443 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1298 // Use a regular load, not a contextual load, to avoid a reference 1444 // Use a regular load, not a contextual load, to avoid a reference
1299 // error. 1445 // error.
1300 __ call(ic, RelocInfo::CODE_TARGET); 1446 __ call(ic, RelocInfo::CODE_TARGET);
1301 __ mov(Operand(esp, 0), eax); 1447 __ mov(Operand(esp, 0), eax);
1302 } else if (proxy != NULL && 1448 } else if (proxy != NULL &&
1303 proxy->var()->slot() != NULL && 1449 proxy->var()->slot() != NULL &&
1304 proxy->var()->slot()->type() == Slot::LOOKUP) { 1450 proxy->var()->slot()->type() == Slot::LOOKUP) {
1305 __ push(esi); 1451 __ push(esi);
1306 __ push(Immediate(proxy->name())); 1452 __ push(Immediate(proxy->name()));
1307 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 1453 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
1308 __ push(eax); 1454 __ push(eax);
1309 } else { 1455 } else {
1310 // This expression cannot throw a reference error at the top level. 1456 // This expression cannot throw a reference error at the top level.
1311 Visit(expr->expression()); 1457 VisitForValue(expr->expression(), kStack);
1312 } 1458 }
1313 1459
1314 __ CallRuntime(Runtime::kTypeof, 1); 1460 __ CallRuntime(Runtime::kTypeof, 1);
1315 Apply(expr->context(), eax); 1461 Apply(expr->context(), eax);
1316 break; 1462 break;
1317 } 1463 }
1318 1464
1319 default: 1465 default:
1320 UNREACHABLE(); 1466 UNREACHABLE();
1321 } 1467 }
(...skipping 12 matching lines...) Expand all
1334 // of the key to detect a named property. 1480 // of the key to detect a named property.
1335 if (prop != NULL) { 1481 if (prop != NULL) {
1336 assign_type = (prop->key()->context() == Expression::kUninitialized) 1482 assign_type = (prop->key()->context() == Expression::kUninitialized)
1337 ? NAMED_PROPERTY 1483 ? NAMED_PROPERTY
1338 : KEYED_PROPERTY; 1484 : KEYED_PROPERTY;
1339 } 1485 }
1340 1486
1341 // Evaluate expression and get value. 1487 // Evaluate expression and get value.
1342 if (assign_type == VARIABLE) { 1488 if (assign_type == VARIABLE) {
1343 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 1489 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
1490 Location saved_location = location_;
1491 location_ = kStack;
1344 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), 1492 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
1345 Expression::kValue); 1493 Expression::kValue);
1494 location_ = saved_location;
1346 } else { 1495 } else {
1347 // Reserve space for result of postfix operation. 1496 // Reserve space for result of postfix operation.
1348 if (expr->is_postfix() && expr->context() != Expression::kEffect) { 1497 if (expr->is_postfix() && expr->context() != Expression::kEffect) {
1349 ASSERT(expr->context() != Expression::kUninitialized); 1498 ASSERT(expr->context() != Expression::kUninitialized);
1350 __ push(Immediate(Smi::FromInt(0))); 1499 __ push(Immediate(Smi::FromInt(0)));
1351 } 1500 }
1352 Visit(prop->obj()); 1501 VisitForValue(prop->obj(), kStack);
1353 ASSERT_EQ(Expression::kValue, prop->obj()->context());
1354 if (assign_type == NAMED_PROPERTY) { 1502 if (assign_type == NAMED_PROPERTY) {
1355 EmitNamedPropertyLoad(prop, Expression::kValue); 1503 EmitNamedPropertyLoad(prop);
1356 } else { 1504 } else {
1357 Visit(prop->key()); 1505 VisitForValue(prop->key(), kStack);
1358 ASSERT_EQ(Expression::kValue, prop->key()->context()); 1506 EmitKeyedPropertyLoad(prop);
1359 EmitKeyedPropertyLoad(prop, Expression::kValue);
1360 } 1507 }
1508 __ push(eax);
1361 } 1509 }
1362 1510
1363 // Convert to number. 1511 // Convert to number.
1364 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 1512 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
1365 1513
1366 // Save result for postfix expressions. 1514 // Save result for postfix expressions.
1367 if (expr->is_postfix()) { 1515 if (expr->is_postfix()) {
1368 switch (expr->context()) { 1516 switch (expr->context()) {
1369 case Expression::kUninitialized: 1517 case Expression::kUninitialized:
1370 UNREACHABLE(); 1518 UNREACHABLE();
1371 case Expression::kEffect: 1519 case Expression::kEffect:
1372 // Do not save result. 1520 // Do not save result.
1373 break; 1521 break;
1374 case Expression::kValue: 1522 case Expression::kValue:
1375 case Expression::kTest: 1523 case Expression::kTest:
1524 case Expression::kValueTest:
1376 case Expression::kTestValue: 1525 case Expression::kTestValue:
1377 case Expression::kValueTest:
1378 // Save the result on the stack. If we have a named or keyed property 1526 // Save the result on the stack. If we have a named or keyed property
1379 // we store the result under the receiver that is currently on top 1527 // we store the result under the receiver that is currently on top
1380 // of the stack. 1528 // of the stack.
1381 switch (assign_type) { 1529 switch (assign_type) {
1382 case VARIABLE: 1530 case VARIABLE:
1383 __ push(eax); 1531 __ push(eax);
1384 break; 1532 break;
1385 case NAMED_PROPERTY: 1533 case NAMED_PROPERTY:
1386 __ mov(Operand(esp, kPointerSize), eax); 1534 __ mov(Operand(esp, kPointerSize), eax);
1387 break; 1535 break;
1388 case KEYED_PROPERTY: 1536 case KEYED_PROPERTY:
1389 __ mov(Operand(esp, 2 * kPointerSize), eax); 1537 __ mov(Operand(esp, 2 * kPointerSize), eax);
1390 break; 1538 break;
1391 } 1539 }
1392 break; 1540 break;
1393 } 1541 }
1394 } 1542 }
1395 1543
1396 // Call runtime for +1/-1. 1544 // Call stub for +1/-1.
1397 __ push(eax); 1545 __ push(eax);
1398 __ push(Immediate(Smi::FromInt(1))); 1546 __ push(Immediate(Smi::FromInt(1)));
1399 if (expr->op() == Token::INC) { 1547 GenericBinaryOpStub stub(expr->binary_op(),
1400 __ CallRuntime(Runtime::kNumberAdd, 2); 1548 NO_OVERWRITE,
1401 } else { 1549 NO_GENERIC_BINARY_FLAGS);
1402 __ CallRuntime(Runtime::kNumberSub, 2); 1550 __ CallStub(&stub);
1403 }
1404 1551
1405 // Store the value returned in eax. 1552 // Store the value returned in eax.
1406 switch (assign_type) { 1553 switch (assign_type) {
1407 case VARIABLE: 1554 case VARIABLE:
1408 __ push(eax);
1409 if (expr->is_postfix()) { 1555 if (expr->is_postfix()) {
1410 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1556 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1411 Expression::kEffect); 1557 Expression::kEffect);
1412 // For all contexts except kEffect: We have the result on 1558 // For all contexts except kEffect: We have the result on
1413 // top of the stack. 1559 // top of the stack.
1414 if (expr->context() != Expression::kEffect) { 1560 if (expr->context() != Expression::kEffect) {
1415 ApplyTOS(expr->context()); 1561 ApplyTOS(expr->context());
1416 } 1562 }
1417 } else { 1563 } else {
1418 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1564 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 case Token::ADD: 1620 case Token::ADD:
1475 case Token::SUB: 1621 case Token::SUB:
1476 case Token::DIV: 1622 case Token::DIV:
1477 case Token::MOD: 1623 case Token::MOD:
1478 case Token::MUL: 1624 case Token::MUL:
1479 case Token::BIT_OR: 1625 case Token::BIT_OR:
1480 case Token::BIT_AND: 1626 case Token::BIT_AND:
1481 case Token::BIT_XOR: 1627 case Token::BIT_XOR:
1482 case Token::SHL: 1628 case Token::SHL:
1483 case Token::SHR: 1629 case Token::SHR:
1484 case Token::SAR: { 1630 case Token::SAR:
1485 ASSERT_EQ(Expression::kValue, expr->left()->context()); 1631 VisitForValue(expr->left(), kStack);
1486 ASSERT_EQ(Expression::kValue, expr->right()->context()); 1632 VisitForValue(expr->right(), kAccumulator);
1633 EmitBinaryOp(expr->op(), expr->context());
1634 break;
1487 1635
1488 Visit(expr->left());
1489 Visit(expr->right());
1490 GenericBinaryOpStub stub(expr->op(),
1491 NO_OVERWRITE,
1492 NO_GENERIC_BINARY_FLAGS);
1493 __ CallStub(&stub);
1494 Apply(expr->context(), eax);
1495
1496 break;
1497 }
1498 default: 1636 default:
1499 UNREACHABLE(); 1637 UNREACHABLE();
1500 } 1638 }
1501 } 1639 }
1502 1640
1503 1641
1504 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1642 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1505 Comment cmnt(masm_, "[ CompareOperation"); 1643 Comment cmnt(masm_, "[ CompareOperation");
1506 ASSERT_EQ(Expression::kValue, expr->left()->context());
1507 ASSERT_EQ(Expression::kValue, expr->right()->context());
1508 Visit(expr->left());
1509 Visit(expr->right());
1510 1644
1511 // Always perform the comparison for its control flow. Pack the result 1645 // Always perform the comparison for its control flow. Pack the result
1512 // into the expression's context after the comparison is performed. 1646 // into the expression's context after the comparison is performed.
1513 Label push_true, push_false, done; 1647 Label materialize_true, materialize_false, done;
1514 // Initially assume we are in a test context. 1648 // Initially assume we are in a test context.
1515 Label* if_true = true_label_; 1649 Label* if_true = true_label_;
1516 Label* if_false = false_label_; 1650 Label* if_false = false_label_;
1517 switch (expr->context()) { 1651 switch (expr->context()) {
1518 case Expression::kUninitialized: 1652 case Expression::kUninitialized:
1519 UNREACHABLE(); 1653 UNREACHABLE();
1520 break; 1654 break;
1521 case Expression::kEffect: 1655 case Expression::kEffect:
1522 if_true = &done; 1656 if_true = &done;
1523 if_false = &done; 1657 if_false = &done;
1524 break; 1658 break;
1525 case Expression::kValue: 1659 case Expression::kValue:
1526 if_true = &push_true; 1660 if_true = &materialize_true;
1527 if_false = &push_false; 1661 if_false = &materialize_false;
1528 break; 1662 break;
1529 case Expression::kTest: 1663 case Expression::kTest:
1530 break; 1664 break;
1531 case Expression::kValueTest: 1665 case Expression::kValueTest:
1532 if_true = &push_true; 1666 if_true = &materialize_true;
1533 break; 1667 break;
1534 case Expression::kTestValue: 1668 case Expression::kTestValue:
1535 if_false = &push_false; 1669 if_false = &materialize_false;
1536 break; 1670 break;
1537 } 1671 }
1538 1672
1673 VisitForValue(expr->left(), kStack);
1539 switch (expr->op()) { 1674 switch (expr->op()) {
1540 case Token::IN: { 1675 case Token::IN:
1676 VisitForValue(expr->right(), kStack);
1541 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 1677 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
1542 __ cmp(eax, Factory::true_value()); 1678 __ cmp(eax, Factory::true_value());
1543 __ j(equal, if_true); 1679 __ j(equal, if_true);
1544 __ jmp(if_false); 1680 __ jmp(if_false);
1545 break; 1681 break;
1546 }
1547 1682
1548 case Token::INSTANCEOF: { 1683 case Token::INSTANCEOF: {
1684 VisitForValue(expr->right(), kStack);
1549 InstanceofStub stub; 1685 InstanceofStub stub;
1550 __ CallStub(&stub); 1686 __ CallStub(&stub);
1551 __ test(eax, Operand(eax)); 1687 __ test(eax, Operand(eax));
1552 __ j(zero, if_true); // The stub returns 0 for true. 1688 __ j(zero, if_true); // The stub returns 0 for true.
1553 __ jmp(if_false); 1689 __ jmp(if_false);
1554 break; 1690 break;
1555 } 1691 }
1556 1692
1557 default: { 1693 default: {
1694 VisitForValue(expr->right(), kAccumulator);
1558 Condition cc = no_condition; 1695 Condition cc = no_condition;
1559 bool strict = false; 1696 bool strict = false;
1560 switch (expr->op()) { 1697 switch (expr->op()) {
1561 case Token::EQ_STRICT: 1698 case Token::EQ_STRICT:
1562 strict = true; 1699 strict = true;
1563 // Fall through 1700 // Fall through
1564 case Token::EQ: 1701 case Token::EQ:
1565 cc = equal; 1702 cc = equal;
1566 __ pop(eax);
1567 __ pop(edx); 1703 __ pop(edx);
1568 break; 1704 break;
1569 case Token::LT: 1705 case Token::LT:
1570 cc = less; 1706 cc = less;
1571 __ pop(eax);
1572 __ pop(edx); 1707 __ pop(edx);
1573 break; 1708 break;
1574 case Token::GT: 1709 case Token::GT:
1575 // Reverse left and right sizes to obtain ECMA-262 conversion order. 1710 // Reverse left and right sizes to obtain ECMA-262 conversion order.
1576 cc = less; 1711 cc = less;
1577 __ pop(edx); 1712 __ mov(edx, result_register());
1578 __ pop(eax); 1713 __ pop(eax);
1579 break; 1714 break;
1580 case Token::LTE: 1715 case Token::LTE:
1581 // Reverse left and right sizes to obtain ECMA-262 conversion order. 1716 // Reverse left and right sizes to obtain ECMA-262 conversion order.
1582 cc = greater_equal; 1717 cc = greater_equal;
1583 __ pop(edx); 1718 __ mov(edx, result_register());
1584 __ pop(eax); 1719 __ pop(eax);
1585 break; 1720 break;
1586 case Token::GTE: 1721 case Token::GTE:
1587 cc = greater_equal; 1722 cc = greater_equal;
1588 __ pop(eax);
1589 __ pop(edx); 1723 __ pop(edx);
1590 break; 1724 break;
1591 case Token::IN: 1725 case Token::IN:
1592 case Token::INSTANCEOF: 1726 case Token::INSTANCEOF:
1593 default: 1727 default:
1594 UNREACHABLE(); 1728 UNREACHABLE();
1595 } 1729 }
1596 1730
1597 // The comparison stub expects the smi vs. smi case to be handled 1731 // The comparison stub expects the smi vs. smi case to be handled
1598 // before it is called. 1732 // before it is called.
(...skipping 10 matching lines...) Expand all
1609 CompareStub stub(cc, strict); 1743 CompareStub stub(cc, strict);
1610 __ CallStub(&stub); 1744 __ CallStub(&stub);
1611 __ test(eax, Operand(eax)); 1745 __ test(eax, Operand(eax));
1612 __ j(cc, if_true); 1746 __ j(cc, if_true);
1613 __ jmp(if_false); 1747 __ jmp(if_false);
1614 } 1748 }
1615 } 1749 }
1616 1750
1617 // Convert the result of the comparison into one expected for this 1751 // Convert the result of the comparison into one expected for this
1618 // expression's context. 1752 // expression's context.
1619 switch (expr->context()) { 1753 Apply(expr->context(), if_true, if_false);
1620 case Expression::kUninitialized:
1621 UNREACHABLE();
1622 break;
1623
1624 case Expression::kEffect:
1625 __ bind(&done);
1626 break;
1627
1628 case Expression::kValue:
1629 __ bind(&push_true);
1630 __ push(Immediate(Factory::true_value()));
1631 __ jmp(&done);
1632 __ bind(&push_false);
1633 __ push(Immediate(Factory::false_value()));
1634 __ bind(&done);
1635 break;
1636
1637 case Expression::kTest:
1638 break;
1639
1640 case Expression::kValueTest:
1641 __ bind(&push_true);
1642 __ push(Immediate(Factory::true_value()));
1643 __ jmp(true_label_);
1644 break;
1645
1646 case Expression::kTestValue:
1647 __ bind(&push_false);
1648 __ push(Immediate(Factory::false_value()));
1649 __ jmp(false_label_);
1650 break;
1651 }
1652 } 1754 }
1653 1755
1654 1756
1655 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { 1757 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
1656 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1758 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1657 Apply(expr->context(), eax); 1759 Apply(expr->context(), eax);
1658 } 1760 }
1659 1761
1660 1762
1661 Register FastCodeGenerator::result_register() { return eax; } 1763 Register FastCodeGenerator::result_register() { return eax; }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1702 __ add(Operand(edx), Immediate(masm_->CodeObject())); 1804 __ add(Operand(edx), Immediate(masm_->CodeObject()));
1703 __ mov(Operand(esp, 0), edx); 1805 __ mov(Operand(esp, 0), edx);
1704 // And return. 1806 // And return.
1705 __ ret(0); 1807 __ ret(0);
1706 } 1808 }
1707 1809
1708 1810
1709 #undef __ 1811 #undef __
1710 1812
1711 } } // namespace v8::internal 1813 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/fast-codegen.cc ('k') | src/runtime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698