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

Powered by Google App Engine
This is Rietveld 408576698