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

Side by Side Diff: src/x64/full-codegen-x64.cc

Issue 3449004: Cleanup of contexts in the full code generator. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 3 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/ia32/macro-assembler-ia32.cc ('k') | src/x64/macro-assembler-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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 } 230 }
231 231
232 232
233 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( 233 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
234 Token::Value op, Expression* left, Expression* right) { 234 Token::Value op, Expression* left, Expression* right) {
235 ASSERT(ShouldInlineSmiCase(op)); 235 ASSERT(ShouldInlineSmiCase(op));
236 return kNoConstants; 236 return kNoConstants;
237 } 237 }
238 238
239 239
240 void FullCodeGenerator::Apply(Expression::Context context, Register reg) { 240 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
241 switch (context) { 241 }
242 case Expression::kUninitialized:
243 UNREACHABLE();
244 242
245 case Expression::kEffect:
246 // Nothing to do.
247 break;
248 243
249 case Expression::kValue: 244 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
250 // Move value into place. 245 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
251 switch (location_) { 246 __ movq(result_register(), slot_operand);
252 case kAccumulator: 247 }
253 if (!reg.is(result_register())) __ movq(result_register(), reg);
254 break;
255 case kStack:
256 __ push(reg);
257 break;
258 }
259 break;
260 248
261 case Expression::kTest: 249
262 // For simplicity we always test the accumulator register. 250 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
263 if (!reg.is(result_register())) __ movq(result_register(), reg); 251 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
264 DoTest(true_label_, false_label_, fall_through_); 252 __ push(slot_operand);
265 break; 253 }
254
255
256 void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
257 codegen()->Move(result_register(), slot);
258 codegen()->DoTest(true_label_, false_label_, fall_through_);
259 }
260
261
262 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
263 }
264
265
266 void FullCodeGenerator::AccumulatorValueContext::Plug(
267 Heap::RootListIndex index) const {
268 __ LoadRoot(result_register(), index);
269 }
270
271
272 void FullCodeGenerator::StackValueContext::Plug(
273 Heap::RootListIndex index) const {
274 __ PushRoot(index);
275 }
276
277
278 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
279 if (index == Heap::kUndefinedValueRootIndex ||
280 index == Heap::kNullValueRootIndex ||
281 index == Heap::kFalseValueRootIndex) {
282 __ jmp(false_label_);
283 } else if (index == Heap::kTrueValueRootIndex) {
284 __ jmp(true_label_);
285 } else {
286 __ LoadRoot(result_register(), index);
287 codegen()->DoTest(true_label_, false_label_, fall_through_);
266 } 288 }
267 } 289 }
268 290
269 291
270 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { 292 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
271 switch (context) { 293 }
272 case Expression::kUninitialized: 294
273 UNREACHABLE(); 295
274 case Expression::kEffect: 296 void FullCodeGenerator::AccumulatorValueContext::Plug(
275 // Nothing to do. 297 Handle<Object> lit) const {
276 break; 298 __ Move(result_register(), lit);
277 case Expression::kValue: { 299 }
278 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); 300
279 switch (location_) { 301
280 case kAccumulator: 302 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
281 __ movq(result_register(), slot_operand); 303 __ Push(lit);
282 break; 304 }
283 case kStack: 305
284 // Memory operands can be pushed directly. 306
285 __ push(slot_operand); 307 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
286 break; 308 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals.
287 } 309 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
288 break; 310 __ jmp(false_label_);
311 } else if (lit->IsTrue() || lit->IsJSObject()) {
312 __ jmp(true_label_);
313 } else if (lit->IsString()) {
314 if (String::cast(*lit)->length() == 0) {
315 __ jmp(false_label_);
316 } else {
317 __ jmp(true_label_);
289 } 318 }
290 319 } else if (lit->IsSmi()) {
291 case Expression::kTest: 320 if (Smi::cast(*lit)->value() == 0) {
292 Move(result_register(), slot); 321 __ jmp(false_label_);
293 DoTest(true_label_, false_label_, fall_through_); 322 } else {
294 break; 323 __ jmp(true_label_);
324 }
325 } else {
326 // For simplicity we always test the accumulator register.
327 __ Move(result_register(), lit);
328 codegen()->DoTest(true_label_, false_label_, fall_through_);
295 } 329 }
296 } 330 }
297 331
298 332
299 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { 333 void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
300 switch (context) { 334 Register reg) const {
301 case Expression::kUninitialized: 335 ASSERT(count > 0);
302 UNREACHABLE(); 336 if (count > 1) __ Drop(count - 1);
303 case Expression::kEffect: 337 __ movq(Operand(rsp, 0), reg);
304 // Nothing to do. 338 }
305 break;
306 case Expression::kValue:
307 switch (location_) {
308 case kAccumulator:
309 __ Move(result_register(), lit->handle());
310 break;
311 case kStack:
312 __ Push(lit->handle());
313 break;
314 }
315 break;
316 339
317 case Expression::kTest: 340
318 __ Move(result_register(), lit->handle()); 341 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
319 DoTest(true_label_, false_label_, fall_through_); 342 Label* materialize_false) const {
320 break; 343 ASSERT_EQ(materialize_true, materialize_false);
344 __ bind(materialize_true);
345 }
346
347
348 void FullCodeGenerator::AccumulatorValueContext::Plug(
349 Label* materialize_true,
350 Label* materialize_false) const {
351 Label done;
352 __ bind(materialize_true);
353 __ Move(result_register(), Factory::true_value());
354 __ jmp(&done);
355 __ bind(materialize_false);
356 __ Move(result_register(), Factory::false_value());
357 __ bind(&done);
358 }
359
360
361 void FullCodeGenerator::StackValueContext::Plug(
362 Label* materialize_true,
363 Label* materialize_false) const {
364 Label done;
365 __ bind(materialize_true);
366 __ Push(Factory::true_value());
367 __ jmp(&done);
368 __ bind(materialize_false);
369 __ Push(Factory::false_value());
370 __ bind(&done);
371 }
372
373
374 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
375 Label* materialize_false) const {
376 }
377
378
379 void FullCodeGenerator::EffectContext::Plug(bool flag) const {
380 }
381
382
383 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
384 Heap::RootListIndex value_root_index =
385 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
386 __ LoadRoot(result_register(), value_root_index);
387 }
388
389
390 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
391 Heap::RootListIndex value_root_index =
392 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
393 __ PushRoot(value_root_index);
394 }
395
396
397 void FullCodeGenerator::TestContext::Plug(bool flag) const {
398 if (flag) {
399 if (true_label_ != fall_through_) __ jmp(true_label_);
400 } else {
401 if (false_label_ != fall_through_) __ jmp(false_label_);
321 } 402 }
322 } 403 }
323 404
324
325 void FullCodeGenerator::ApplyTOS(Expression::Context context) {
326 switch (context) {
327 case Expression::kUninitialized:
328 UNREACHABLE();
329
330 case Expression::kEffect:
331 __ Drop(1);
332 break;
333
334 case Expression::kValue:
335 switch (location_) {
336 case kAccumulator:
337 __ pop(result_register());
338 break;
339 case kStack:
340 break;
341 }
342 break;
343
344 case Expression::kTest:
345 __ pop(result_register());
346 DoTest(true_label_, false_label_, fall_through_);
347 break;
348 }
349 }
350
351
352 void FullCodeGenerator::DropAndApply(int count,
353 Expression::Context context,
354 Register reg) {
355 ASSERT(count > 0);
356 ASSERT(!reg.is(rsp));
357 switch (context) {
358 case Expression::kUninitialized:
359 UNREACHABLE();
360
361 case Expression::kEffect:
362 __ Drop(count);
363 break;
364
365 case Expression::kValue:
366 switch (location_) {
367 case kAccumulator:
368 __ Drop(count);
369 if (!reg.is(result_register())) __ movq(result_register(), reg);
370 break;
371 case kStack:
372 if (count > 1) __ Drop(count - 1);
373 __ movq(Operand(rsp, 0), reg);
374 break;
375 }
376 break;
377
378 case Expression::kTest:
379 __ Drop(count);
380 if (!reg.is(result_register())) __ movq(result_register(), reg);
381 DoTest(true_label_, false_label_, fall_through_);
382 break;
383 }
384 }
385
386
387 void FullCodeGenerator::Apply(Expression::Context context,
388 Label* materialize_true,
389 Label* materialize_false) {
390 switch (context) {
391 case Expression::kUninitialized:
392
393 case Expression::kEffect:
394 ASSERT_EQ(materialize_true, materialize_false);
395 __ bind(materialize_true);
396 break;
397
398 case Expression::kValue: {
399 Label done;
400 switch (location_) {
401 case kAccumulator:
402 __ bind(materialize_true);
403 __ Move(result_register(), Factory::true_value());
404 __ jmp(&done);
405 __ bind(materialize_false);
406 __ Move(result_register(), Factory::false_value());
407 break;
408 case kStack:
409 __ bind(materialize_true);
410 __ Push(Factory::true_value());
411 __ jmp(&done);
412 __ bind(materialize_false);
413 __ Push(Factory::false_value());
414 break;
415 }
416 __ bind(&done);
417 break;
418 }
419
420 case Expression::kTest:
421 break;
422 }
423 }
424
425
426 // Convert constant control flow (true or false) to the result expected for
427 // a given expression context.
428 void FullCodeGenerator::Apply(Expression::Context context, bool flag) {
429 switch (context) {
430 case Expression::kUninitialized:
431 UNREACHABLE();
432 break;
433 case Expression::kEffect:
434 break;
435 case Expression::kValue: {
436 Heap::RootListIndex value_root_index =
437 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
438 switch (location_) {
439 case kAccumulator:
440 __ LoadRoot(result_register(), value_root_index);
441 break;
442 case kStack:
443 __ PushRoot(value_root_index);
444 break;
445 }
446 break;
447 }
448 case Expression::kTest:
449 if (flag) {
450 if (true_label_ != fall_through_) __ jmp(true_label_);
451 } else {
452 if (false_label_ != fall_through_) __ jmp(false_label_);
453 }
454 break;
455 }
456 }
457
458 405
459 void FullCodeGenerator::DoTest(Label* if_true, 406 void FullCodeGenerator::DoTest(Label* if_true,
460 Label* if_false, 407 Label* if_false,
461 Label* fall_through) { 408 Label* fall_through) {
462 // Emit the inlined tests assumed by the stub. 409 // Emit the inlined tests assumed by the stub.
463 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); 410 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex);
464 __ j(equal, if_false); 411 __ j(equal, if_false);
465 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); 412 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
466 __ j(equal, if_true); 413 __ j(equal, if_true);
467 __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); 414 __ CompareRoot(result_register(), Heap::kFalseValueRootIndex);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 Property* prop = variable->AsProperty(); 495 Property* prop = variable->AsProperty();
549 496
550 if (slot != NULL) { 497 if (slot != NULL) {
551 switch (slot->type()) { 498 switch (slot->type()) {
552 case Slot::PARAMETER: 499 case Slot::PARAMETER:
553 case Slot::LOCAL: 500 case Slot::LOCAL:
554 if (mode == Variable::CONST) { 501 if (mode == Variable::CONST) {
555 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 502 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
556 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); 503 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
557 } else if (function != NULL) { 504 } else if (function != NULL) {
558 VisitForValue(function, kAccumulator); 505 VisitForAccumulatorValue(function);
559 __ movq(Operand(rbp, SlotOffset(slot)), result_register()); 506 __ movq(Operand(rbp, SlotOffset(slot)), result_register());
560 } 507 }
561 break; 508 break;
562 509
563 case Slot::CONTEXT: 510 case Slot::CONTEXT:
564 // We bypass the general EmitSlotSearch because we know more about 511 // We bypass the general EmitSlotSearch because we know more about
565 // this specific context. 512 // this specific context.
566 513
567 // The variable in the decl always resides in the current context. 514 // The variable in the decl always resides in the current context.
568 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 515 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
569 if (FLAG_debug_code) { 516 if (FLAG_debug_code) {
570 // Check if we have the correct context pointer. 517 // Check if we have the correct context pointer.
571 __ movq(rbx, ContextOperand(rsi, Context::FCONTEXT_INDEX)); 518 __ movq(rbx, ContextOperand(rsi, Context::FCONTEXT_INDEX));
572 __ cmpq(rbx, rsi); 519 __ cmpq(rbx, rsi);
573 __ Check(equal, "Unexpected declaration in current context."); 520 __ Check(equal, "Unexpected declaration in current context.");
574 } 521 }
575 if (mode == Variable::CONST) { 522 if (mode == Variable::CONST) {
576 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 523 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
577 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister); 524 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
578 // No write barrier since the hole value is in old space. 525 // No write barrier since the hole value is in old space.
579 } else if (function != NULL) { 526 } else if (function != NULL) {
580 VisitForValue(function, kAccumulator); 527 VisitForAccumulatorValue(function);
581 __ movq(ContextOperand(rsi, slot->index()), result_register()); 528 __ movq(ContextOperand(rsi, slot->index()), result_register());
582 int offset = Context::SlotOffset(slot->index()); 529 int offset = Context::SlotOffset(slot->index());
583 __ movq(rbx, rsi); 530 __ movq(rbx, rsi);
584 __ RecordWrite(rbx, offset, result_register(), rcx); 531 __ RecordWrite(rbx, offset, result_register(), rcx);
585 } 532 }
586 break; 533 break;
587 534
588 case Slot::LOOKUP: { 535 case Slot::LOOKUP: {
589 __ push(rsi); 536 __ push(rsi);
590 __ Push(variable->name()); 537 __ Push(variable->name());
591 // Declaration nodes are always introduced in one of two modes. 538 // Declaration nodes are always introduced in one of two modes.
592 ASSERT(mode == Variable::VAR || mode == Variable::CONST); 539 ASSERT(mode == Variable::VAR || mode == Variable::CONST);
593 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; 540 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
594 __ Push(Smi::FromInt(attr)); 541 __ Push(Smi::FromInt(attr));
595 // Push initial value, if any. 542 // Push initial value, if any.
596 // Note: For variables we must not push an initial value (such as 543 // Note: For variables we must not push an initial value (such as
597 // 'undefined') because we may have a (legal) redeclaration and we 544 // 'undefined') because we may have a (legal) redeclaration and we
598 // must not destroy the current value. 545 // must not destroy the current value.
599 if (mode == Variable::CONST) { 546 if (mode == Variable::CONST) {
600 __ PushRoot(Heap::kTheHoleValueRootIndex); 547 __ PushRoot(Heap::kTheHoleValueRootIndex);
601 } else if (function != NULL) { 548 } else if (function != NULL) {
602 VisitForValue(function, kStack); 549 VisitForStackValue(function);
603 } else { 550 } else {
604 __ Push(Smi::FromInt(0)); // no initial value! 551 __ Push(Smi::FromInt(0)); // no initial value!
605 } 552 }
606 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 553 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
607 break; 554 break;
608 } 555 }
609 } 556 }
610 557
611 } else if (prop != NULL) { 558 } else if (prop != NULL) {
612 if (function != NULL || mode == Variable::CONST) { 559 if (function != NULL || mode == Variable::CONST) {
613 // We are declaring a function or constant that rewrites to a 560 // We are declaring a function or constant that rewrites to a
614 // property. Use (keyed) IC to set the initial value. 561 // property. Use (keyed) IC to set the initial value.
615 VisitForValue(prop->obj(), kStack); 562 VisitForStackValue(prop->obj());
616 if (function != NULL) { 563 if (function != NULL) {
617 VisitForValue(prop->key(), kStack); 564 VisitForStackValue(prop->key());
618 VisitForValue(function, kAccumulator); 565 VisitForAccumulatorValue(function);
619 __ pop(rcx); 566 __ pop(rcx);
620 } else { 567 } else {
621 VisitForValue(prop->key(), kAccumulator); 568 VisitForAccumulatorValue(prop->key());
622 __ movq(rcx, result_register()); 569 __ movq(rcx, result_register());
623 __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); 570 __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
624 } 571 }
625 __ pop(rdx); 572 __ pop(rdx);
626 573
627 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 574 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
628 __ call(ic, RelocInfo::CODE_TARGET); 575 __ call(ic, RelocInfo::CODE_TARGET);
629 // Absence of a test rax instruction following the call 576 // Absence of a test rax instruction following the call
630 // indicates that none of the load was inlined. 577 // indicates that none of the load was inlined.
631 __ nop(); 578 __ nop();
(...skipping 15 matching lines...) Expand all
647 __ CallRuntime(Runtime::kDeclareGlobals, 3); 594 __ CallRuntime(Runtime::kDeclareGlobals, 3);
648 // Return value is ignored. 595 // Return value is ignored.
649 } 596 }
650 597
651 598
652 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 599 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
653 Comment cmnt(masm_, "[ SwitchStatement"); 600 Comment cmnt(masm_, "[ SwitchStatement");
654 Breakable nested_statement(this, stmt); 601 Breakable nested_statement(this, stmt);
655 SetStatementPosition(stmt); 602 SetStatementPosition(stmt);
656 // Keep the switch value on the stack until a case matches. 603 // Keep the switch value on the stack until a case matches.
657 VisitForValue(stmt->tag(), kStack); 604 VisitForStackValue(stmt->tag());
658 605
659 ZoneList<CaseClause*>* clauses = stmt->cases(); 606 ZoneList<CaseClause*>* clauses = stmt->cases();
660 CaseClause* default_clause = NULL; // Can occur anywhere in the list. 607 CaseClause* default_clause = NULL; // Can occur anywhere in the list.
661 608
662 Label next_test; // Recycled for each test. 609 Label next_test; // Recycled for each test.
663 // Compile all the tests with branches to their bodies. 610 // Compile all the tests with branches to their bodies.
664 for (int i = 0; i < clauses->length(); i++) { 611 for (int i = 0; i < clauses->length(); i++) {
665 CaseClause* clause = clauses->at(i); 612 CaseClause* clause = clauses->at(i);
666 // The default is not a test, but remember it as final fall through. 613 // The default is not a test, but remember it as final fall through.
667 if (clause->is_default()) { 614 if (clause->is_default()) {
668 default_clause = clause; 615 default_clause = clause;
669 continue; 616 continue;
670 } 617 }
671 618
672 Comment cmnt(masm_, "[ Case comparison"); 619 Comment cmnt(masm_, "[ Case comparison");
673 __ bind(&next_test); 620 __ bind(&next_test);
674 next_test.Unuse(); 621 next_test.Unuse();
675 622
676 // Compile the label expression. 623 // Compile the label expression.
677 VisitForValue(clause->label(), kAccumulator); 624 VisitForAccumulatorValue(clause->label());
678 625
679 // Perform the comparison as if via '==='. 626 // Perform the comparison as if via '==='.
680 if (ShouldInlineSmiCase(Token::EQ_STRICT)) { 627 if (ShouldInlineSmiCase(Token::EQ_STRICT)) {
681 Label slow_case; 628 Label slow_case;
682 __ movq(rdx, Operand(rsp, 0)); // Switch value. 629 __ movq(rdx, Operand(rsp, 0)); // Switch value.
683 __ JumpIfNotBothSmi(rdx, rax, &slow_case); 630 __ JumpIfNotBothSmi(rdx, rax, &slow_case);
684 __ SmiCompare(rdx, rax); 631 __ SmiCompare(rdx, rax);
685 __ j(not_equal, &next_test); 632 __ j(not_equal, &next_test);
686 __ Drop(1); // Switch value is no longer needed. 633 __ Drop(1); // Switch value is no longer needed.
687 __ jmp(clause->body_target()->entry_label()); 634 __ jmp(clause->body_target()->entry_label());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 Comment cmnt(masm_, "[ ForInStatement"); 669 Comment cmnt(masm_, "[ ForInStatement");
723 SetStatementPosition(stmt); 670 SetStatementPosition(stmt);
724 671
725 Label loop, exit; 672 Label loop, exit;
726 ForIn loop_statement(this, stmt); 673 ForIn loop_statement(this, stmt);
727 increment_loop_depth(); 674 increment_loop_depth();
728 675
729 // Get the object to enumerate over. Both SpiderMonkey and JSC 676 // Get the object to enumerate over. Both SpiderMonkey and JSC
730 // ignore null and undefined in contrast to the specification; see 677 // ignore null and undefined in contrast to the specification; see
731 // ECMA-262 section 12.6.4. 678 // ECMA-262 section 12.6.4.
732 VisitForValue(stmt->enumerable(), kAccumulator); 679 VisitForAccumulatorValue(stmt->enumerable());
733 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 680 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
734 __ j(equal, &exit); 681 __ j(equal, &exit);
735 __ CompareRoot(rax, Heap::kNullValueRootIndex); 682 __ CompareRoot(rax, Heap::kNullValueRootIndex);
736 __ j(equal, &exit); 683 __ j(equal, &exit);
737 684
738 // Convert the object to a JS object. 685 // Convert the object to a JS object.
739 Label convert, done_convert; 686 Label convert, done_convert;
740 __ JumpIfSmi(rax, &convert); 687 __ JumpIfSmi(rax, &convert);
741 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 688 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
742 __ j(above_equal, &done_convert); 689 __ j(above_equal, &done_convert);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 // space for nested functions that don't need literals cloning. 807 // space for nested functions that don't need literals cloning.
861 if (scope()->is_function_scope() && info->num_literals() == 0) { 808 if (scope()->is_function_scope() && info->num_literals() == 0) {
862 FastNewClosureStub stub; 809 FastNewClosureStub stub;
863 __ Push(info); 810 __ Push(info);
864 __ CallStub(&stub); 811 __ CallStub(&stub);
865 } else { 812 } else {
866 __ push(rsi); 813 __ push(rsi);
867 __ Push(info); 814 __ Push(info);
868 __ CallRuntime(Runtime::kNewClosure, 2); 815 __ CallRuntime(Runtime::kNewClosure, 2);
869 } 816 }
870 Apply(context_, rax); 817 context()->Plug(rax);
871 } 818 }
872 819
873 820
874 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 821 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
875 Comment cmnt(masm_, "[ VariableProxy"); 822 Comment cmnt(masm_, "[ VariableProxy");
876 EmitVariableLoad(expr->var(), context_); 823 EmitVariableLoad(expr->var());
877 } 824 }
878 825
879 826
880 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( 827 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
881 Slot* slot, 828 Slot* slot,
882 TypeofState typeof_state, 829 TypeofState typeof_state,
883 Label* slow) { 830 Label* slow) {
884 Register context = rsi; 831 Register context = rsi;
885 Register temp = rdx; 832 Register temp = rdx;
886 833
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 963 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1017 __ call(ic, RelocInfo::CODE_TARGET); 964 __ call(ic, RelocInfo::CODE_TARGET);
1018 __ jmp(done); 965 __ jmp(done);
1019 } 966 }
1020 } 967 }
1021 } 968 }
1022 } 969 }
1023 } 970 }
1024 971
1025 972
1026 void FullCodeGenerator::EmitVariableLoad(Variable* var, 973 void FullCodeGenerator::EmitVariableLoad(Variable* var) {
1027 Expression::Context context) {
1028 // Four cases: non-this global variables, lookup slots, all other 974 // Four cases: non-this global variables, lookup slots, all other
1029 // types of slots, and parameters that rewrite to explicit property 975 // types of slots, and parameters that rewrite to explicit property
1030 // accesses on the arguments object. 976 // accesses on the arguments object.
1031 Slot* slot = var->slot(); 977 Slot* slot = var->slot();
1032 Property* property = var->AsProperty(); 978 Property* property = var->AsProperty();
1033 979
1034 if (var->is_global() && !var->is_this()) { 980 if (var->is_global() && !var->is_this()) {
1035 Comment cmnt(masm_, "Global variable"); 981 Comment cmnt(masm_, "Global variable");
1036 // Use inline caching. Variable name is passed in rcx and the global 982 // Use inline caching. Variable name is passed in rcx and the global
1037 // object on the stack. 983 // object on the stack.
1038 __ Move(rcx, var->name()); 984 __ Move(rcx, var->name());
1039 __ movq(rax, CodeGenerator::GlobalObject()); 985 __ movq(rax, CodeGenerator::GlobalObject());
1040 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 986 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1041 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 987 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1042 // A test rax instruction following the call is used by the IC to 988 // A test rax instruction following the call is used by the IC to
1043 // indicate that the inobject property case was inlined. Ensure there 989 // indicate that the inobject property case was inlined. Ensure there
1044 // is no test rax instruction here. 990 // is no test rax instruction here.
1045 __ nop(); 991 __ nop();
1046 Apply(context, rax); 992 context()->Plug(rax);
1047 993
1048 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 994 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1049 Label done, slow; 995 Label done, slow;
1050 996
1051 // Generate code for loading from variables potentially shadowed 997 // Generate code for loading from variables potentially shadowed
1052 // by eval-introduced variables. 998 // by eval-introduced variables.
1053 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); 999 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
1054 1000
1055 __ bind(&slow); 1001 __ bind(&slow);
1056 Comment cmnt(masm_, "Lookup slot"); 1002 Comment cmnt(masm_, "Lookup slot");
1057 __ push(rsi); // Context. 1003 __ push(rsi); // Context.
1058 __ Push(var->name()); 1004 __ Push(var->name());
1059 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1005 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1060 __ bind(&done); 1006 __ bind(&done);
1061 1007
1062 Apply(context, rax); 1008 context()->Plug(rax);
1063 1009
1064 } else if (slot != NULL) { 1010 } else if (slot != NULL) {
1065 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1011 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1066 ? "Context slot" 1012 ? "Context slot"
1067 : "Stack slot"); 1013 : "Stack slot");
1068 if (var->mode() == Variable::CONST) { 1014 if (var->mode() == Variable::CONST) {
1069 // Constants may be the hole value if they have not been initialized. 1015 // Constants may be the hole value if they have not been initialized.
1070 // Unhole them. 1016 // Unhole them.
1071 Label done; 1017 Label done;
1072 MemOperand slot_operand = EmitSlotSearch(slot, rax); 1018 MemOperand slot_operand = EmitSlotSearch(slot, rax);
1073 __ movq(rax, slot_operand); 1019 __ movq(rax, slot_operand);
1074 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1020 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1075 __ j(not_equal, &done); 1021 __ j(not_equal, &done);
1076 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1022 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1077 __ bind(&done); 1023 __ bind(&done);
1078 Apply(context, rax); 1024 context()->Plug(rax);
1079 } else { 1025 } else {
1080 Apply(context, slot); 1026 context()->Plug(slot);
1081 } 1027 }
1082 1028
1083 } else { 1029 } else {
1084 Comment cmnt(masm_, "Rewritten parameter"); 1030 Comment cmnt(masm_, "Rewritten parameter");
1085 ASSERT_NOT_NULL(property); 1031 ASSERT_NOT_NULL(property);
1086 // Rewritten parameter accesses are of the form "slot[literal]". 1032 // Rewritten parameter accesses are of the form "slot[literal]".
1087 1033
1088 // Assert that the object is in a slot. 1034 // Assert that the object is in a slot.
1089 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 1035 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1090 ASSERT_NOT_NULL(object_var); 1036 ASSERT_NOT_NULL(object_var);
(...skipping 11 matching lines...) Expand all
1102 1048
1103 // Load the key. 1049 // Load the key.
1104 __ Move(rax, key_literal->handle()); 1050 __ Move(rax, key_literal->handle());
1105 1051
1106 // Do a keyed property load. 1052 // Do a keyed property load.
1107 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1053 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1108 __ call(ic, RelocInfo::CODE_TARGET); 1054 __ call(ic, RelocInfo::CODE_TARGET);
1109 // Notice: We must not have a "test rax, ..." instruction after the 1055 // Notice: We must not have a "test rax, ..." instruction after the
1110 // call. It is treated specially by the LoadIC code. 1056 // call. It is treated specially by the LoadIC code.
1111 __ nop(); 1057 __ nop();
1112 Apply(context, rax); 1058 context()->Plug(rax);
1113 } 1059 }
1114 } 1060 }
1115 1061
1116 1062
1117 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1063 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1118 Comment cmnt(masm_, "[ RegExpLiteral"); 1064 Comment cmnt(masm_, "[ RegExpLiteral");
1119 Label materialized; 1065 Label materialized;
1120 // Registers will be used as follows: 1066 // Registers will be used as follows:
1121 // rdi = JS function. 1067 // rdi = JS function.
1122 // rcx = literals array. 1068 // rcx = literals array.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1157 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 1103 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1158 __ movq(rdx, FieldOperand(rbx, i)); 1104 __ movq(rdx, FieldOperand(rbx, i));
1159 __ movq(rcx, FieldOperand(rbx, i + kPointerSize)); 1105 __ movq(rcx, FieldOperand(rbx, i + kPointerSize));
1160 __ movq(FieldOperand(rax, i), rdx); 1106 __ movq(FieldOperand(rax, i), rdx);
1161 __ movq(FieldOperand(rax, i + kPointerSize), rcx); 1107 __ movq(FieldOperand(rax, i + kPointerSize), rcx);
1162 } 1108 }
1163 if ((size % (2 * kPointerSize)) != 0) { 1109 if ((size % (2 * kPointerSize)) != 0) {
1164 __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); 1110 __ movq(rdx, FieldOperand(rbx, size - kPointerSize));
1165 __ movq(FieldOperand(rax, size - kPointerSize), rdx); 1111 __ movq(FieldOperand(rax, size - kPointerSize), rdx);
1166 } 1112 }
1167 Apply(context_, rax); 1113 context()->Plug(rax);
1168 } 1114 }
1169 1115
1170 1116
1171 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1117 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1172 Comment cmnt(masm_, "[ ObjectLiteral"); 1118 Comment cmnt(masm_, "[ ObjectLiteral");
1173 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1119 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1174 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 1120 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
1175 __ Push(Smi::FromInt(expr->literal_index())); 1121 __ Push(Smi::FromInt(expr->literal_index()));
1176 __ Push(expr->constant_properties()); 1122 __ Push(expr->constant_properties());
1177 __ Push(Smi::FromInt(expr->fast_elements() ? 1 : 0)); 1123 __ Push(Smi::FromInt(expr->fast_elements() ? 1 : 0));
(...skipping 18 matching lines...) Expand all
1196 result_saved = true; 1142 result_saved = true;
1197 } 1143 }
1198 switch (property->kind()) { 1144 switch (property->kind()) {
1199 case ObjectLiteral::Property::CONSTANT: 1145 case ObjectLiteral::Property::CONSTANT:
1200 UNREACHABLE(); 1146 UNREACHABLE();
1201 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1147 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1202 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1148 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1203 // Fall through. 1149 // Fall through.
1204 case ObjectLiteral::Property::COMPUTED: 1150 case ObjectLiteral::Property::COMPUTED:
1205 if (key->handle()->IsSymbol()) { 1151 if (key->handle()->IsSymbol()) {
1206 VisitForValue(value, kAccumulator); 1152 VisitForAccumulatorValue(value);
1207 __ Move(rcx, key->handle()); 1153 __ Move(rcx, key->handle());
1208 __ movq(rdx, Operand(rsp, 0)); 1154 __ movq(rdx, Operand(rsp, 0));
1209 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1155 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1210 __ call(ic, RelocInfo::CODE_TARGET); 1156 __ call(ic, RelocInfo::CODE_TARGET);
1211 __ nop(); 1157 __ nop();
1212 break; 1158 break;
1213 } 1159 }
1214 // Fall through. 1160 // Fall through.
1215 case ObjectLiteral::Property::PROTOTYPE: 1161 case ObjectLiteral::Property::PROTOTYPE:
1216 __ push(Operand(rsp, 0)); // Duplicate receiver. 1162 __ push(Operand(rsp, 0)); // Duplicate receiver.
1217 VisitForValue(key, kStack); 1163 VisitForStackValue(key);
1218 VisitForValue(value, kStack); 1164 VisitForStackValue(value);
1219 __ CallRuntime(Runtime::kSetProperty, 3); 1165 __ CallRuntime(Runtime::kSetProperty, 3);
1220 break; 1166 break;
1221 case ObjectLiteral::Property::SETTER: 1167 case ObjectLiteral::Property::SETTER:
1222 case ObjectLiteral::Property::GETTER: 1168 case ObjectLiteral::Property::GETTER:
1223 __ push(Operand(rsp, 0)); // Duplicate receiver. 1169 __ push(Operand(rsp, 0)); // Duplicate receiver.
1224 VisitForValue(key, kStack); 1170 VisitForStackValue(key);
1225 __ Push(property->kind() == ObjectLiteral::Property::SETTER ? 1171 __ Push(property->kind() == ObjectLiteral::Property::SETTER ?
1226 Smi::FromInt(1) : 1172 Smi::FromInt(1) :
1227 Smi::FromInt(0)); 1173 Smi::FromInt(0));
1228 VisitForValue(value, kStack); 1174 VisitForStackValue(value);
1229 __ CallRuntime(Runtime::kDefineAccessor, 4); 1175 __ CallRuntime(Runtime::kDefineAccessor, 4);
1230 break; 1176 break;
1231 } 1177 }
1232 } 1178 }
1233 1179
1234 if (result_saved) { 1180 if (result_saved) {
1235 ApplyTOS(context_); 1181 context()->PlugTOS();
1236 } else { 1182 } else {
1237 Apply(context_, rax); 1183 context()->Plug(rax);
1238 } 1184 }
1239 } 1185 }
1240 1186
1241 1187
1242 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1188 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1243 Comment cmnt(masm_, "[ ArrayLiteral"); 1189 Comment cmnt(masm_, "[ ArrayLiteral");
1244 1190
1245 ZoneList<Expression*>* subexprs = expr->values(); 1191 ZoneList<Expression*>* subexprs = expr->values();
1246 int length = subexprs->length(); 1192 int length = subexprs->length();
1247 1193
(...skipping 26 matching lines...) Expand all
1274 // is already set in the cloned array. 1220 // is already set in the cloned array.
1275 if (subexpr->AsLiteral() != NULL || 1221 if (subexpr->AsLiteral() != NULL ||
1276 CompileTimeValue::IsCompileTimeValue(subexpr)) { 1222 CompileTimeValue::IsCompileTimeValue(subexpr)) {
1277 continue; 1223 continue;
1278 } 1224 }
1279 1225
1280 if (!result_saved) { 1226 if (!result_saved) {
1281 __ push(rax); 1227 __ push(rax);
1282 result_saved = true; 1228 result_saved = true;
1283 } 1229 }
1284 VisitForValue(subexpr, kAccumulator); 1230 VisitForAccumulatorValue(subexpr);
1285 1231
1286 // Store the subexpression value in the array's elements. 1232 // Store the subexpression value in the array's elements.
1287 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 1233 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal.
1288 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 1234 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
1289 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1235 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1290 __ movq(FieldOperand(rbx, offset), result_register()); 1236 __ movq(FieldOperand(rbx, offset), result_register());
1291 1237
1292 // Update the write barrier for the array store. 1238 // Update the write barrier for the array store.
1293 __ RecordWrite(rbx, offset, result_register(), rcx); 1239 __ RecordWrite(rbx, offset, result_register(), rcx);
1294 } 1240 }
1295 1241
1296 if (result_saved) { 1242 if (result_saved) {
1297 ApplyTOS(context_); 1243 context()->PlugTOS();
1298 } else { 1244 } else {
1299 Apply(context_, rax); 1245 context()->Plug(rax);
1300 } 1246 }
1301 } 1247 }
1302 1248
1303 1249
1304 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1250 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1305 Comment cmnt(masm_, "[ Assignment"); 1251 Comment cmnt(masm_, "[ Assignment");
1306 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1252 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1307 // on the left-hand side. 1253 // on the left-hand side.
1308 if (!expr->target()->IsValidLeftHandSide()) { 1254 if (!expr->target()->IsValidLeftHandSide()) {
1309 VisitForEffect(expr->target()); 1255 VisitForEffect(expr->target());
(...skipping 12 matching lines...) Expand all
1322 } 1268 }
1323 1269
1324 // Evaluate LHS expression. 1270 // Evaluate LHS expression.
1325 switch (assign_type) { 1271 switch (assign_type) {
1326 case VARIABLE: 1272 case VARIABLE:
1327 // Nothing to do here. 1273 // Nothing to do here.
1328 break; 1274 break;
1329 case NAMED_PROPERTY: 1275 case NAMED_PROPERTY:
1330 if (expr->is_compound()) { 1276 if (expr->is_compound()) {
1331 // We need the receiver both on the stack and in the accumulator. 1277 // We need the receiver both on the stack and in the accumulator.
1332 VisitForValue(property->obj(), kAccumulator); 1278 VisitForAccumulatorValue(property->obj());
1333 __ push(result_register()); 1279 __ push(result_register());
1334 } else { 1280 } else {
1335 VisitForValue(property->obj(), kStack); 1281 VisitForStackValue(property->obj());
1336 } 1282 }
1337 break; 1283 break;
1338 case KEYED_PROPERTY: 1284 case KEYED_PROPERTY:
1339 if (expr->is_compound()) { 1285 if (expr->is_compound()) {
1340 VisitForValue(property->obj(), kStack); 1286 VisitForStackValue(property->obj());
1341 VisitForValue(property->key(), kAccumulator); 1287 VisitForAccumulatorValue(property->key());
1342 __ movq(rdx, Operand(rsp, 0)); 1288 __ movq(rdx, Operand(rsp, 0));
1343 __ push(rax); 1289 __ push(rax);
1344 } else { 1290 } else {
1345 VisitForValue(property->obj(), kStack); 1291 VisitForStackValue(property->obj());
1346 VisitForValue(property->key(), kStack); 1292 VisitForStackValue(property->key());
1347 } 1293 }
1348 break; 1294 break;
1349 } 1295 }
1350 1296
1351 if (expr->is_compound()) { 1297 if (expr->is_compound()) {
1352 Location saved_location = location_; 1298 { AccumulatorValueContext context(this);
1353 location_ = kAccumulator; 1299 switch (assign_type) {
1354 switch (assign_type) { 1300 case VARIABLE:
1355 case VARIABLE: 1301 EmitVariableLoad(expr->target()->AsVariableProxy()->var());
1356 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), 1302 break;
1357 Expression::kValue); 1303 case NAMED_PROPERTY:
1358 break; 1304 EmitNamedPropertyLoad(property);
1359 case NAMED_PROPERTY: 1305 break;
1360 EmitNamedPropertyLoad(property); 1306 case KEYED_PROPERTY:
1361 break; 1307 EmitKeyedPropertyLoad(property);
1362 case KEYED_PROPERTY: 1308 break;
1363 EmitKeyedPropertyLoad(property); 1309 }
1364 break;
1365 } 1310 }
1366 1311
1367 Token::Value op = expr->binary_op(); 1312 Token::Value op = expr->binary_op();
1368 ConstantOperand constant = ShouldInlineSmiCase(op) 1313 ConstantOperand constant = ShouldInlineSmiCase(op)
1369 ? GetConstantOperand(op, expr->target(), expr->value()) 1314 ? GetConstantOperand(op, expr->target(), expr->value())
1370 : kNoConstants; 1315 : kNoConstants;
1371 ASSERT(constant == kRightConstant || constant == kNoConstants); 1316 ASSERT(constant == kRightConstant || constant == kNoConstants);
1372 if (constant == kNoConstants) { 1317 if (constant == kNoConstants) {
1373 __ push(rax); // Left operand goes on the stack. 1318 __ push(rax); // Left operand goes on the stack.
1374 VisitForValue(expr->value(), kAccumulator); 1319 VisitForAccumulatorValue(expr->value());
1375 } 1320 }
1376 1321
1377 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 1322 OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1378 ? OVERWRITE_RIGHT 1323 ? OVERWRITE_RIGHT
1379 : NO_OVERWRITE; 1324 : NO_OVERWRITE;
1380 SetSourcePosition(expr->position() + 1); 1325 SetSourcePosition(expr->position() + 1);
1326 AccumulatorValueContext context(this);
1381 if (ShouldInlineSmiCase(op)) { 1327 if (ShouldInlineSmiCase(op)) {
1382 EmitInlineSmiBinaryOp(expr, 1328 EmitInlineSmiBinaryOp(expr,
1383 op, 1329 op,
1384 Expression::kValue,
1385 mode, 1330 mode,
1386 expr->target(), 1331 expr->target(),
1387 expr->value(), 1332 expr->value(),
1388 constant); 1333 constant);
1389 } else { 1334 } else {
1390 EmitBinaryOp(op, Expression::kValue, mode); 1335 EmitBinaryOp(op, mode);
1391 } 1336 }
1392 location_ = saved_location;
1393
1394 } else { 1337 } else {
1395 VisitForValue(expr->value(), kAccumulator); 1338 VisitForAccumulatorValue(expr->value());
1396 } 1339 }
1397 1340
1398 // Record source position before possible IC call. 1341 // Record source position before possible IC call.
1399 SetSourcePosition(expr->position()); 1342 SetSourcePosition(expr->position());
1400 1343
1401 // Store the value. 1344 // Store the value.
1402 switch (assign_type) { 1345 switch (assign_type) {
1403 case VARIABLE: 1346 case VARIABLE:
1404 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1347 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1405 expr->op(), 1348 expr->op());
1406 context_);
1407 break; 1349 break;
1408 case NAMED_PROPERTY: 1350 case NAMED_PROPERTY:
1409 EmitNamedPropertyAssignment(expr); 1351 EmitNamedPropertyAssignment(expr);
1410 break; 1352 break;
1411 case KEYED_PROPERTY: 1353 case KEYED_PROPERTY:
1412 EmitKeyedPropertyAssignment(expr); 1354 EmitKeyedPropertyAssignment(expr);
1413 break; 1355 break;
1414 } 1356 }
1415 } 1357 }
1416 1358
(...skipping 11 matching lines...) Expand all
1428 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1370 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1429 SetSourcePosition(prop->position()); 1371 SetSourcePosition(prop->position());
1430 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1372 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1431 __ Call(ic, RelocInfo::CODE_TARGET); 1373 __ Call(ic, RelocInfo::CODE_TARGET);
1432 __ nop(); 1374 __ nop();
1433 } 1375 }
1434 1376
1435 1377
1436 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, 1378 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
1437 Token::Value op, 1379 Token::Value op,
1438 Expression::Context context,
1439 OverwriteMode mode, 1380 OverwriteMode mode,
1440 Expression* left, 1381 Expression* left,
1441 Expression* right, 1382 Expression* right,
1442 ConstantOperand constant) { 1383 ConstantOperand constant) {
1443 ASSERT(constant == kNoConstants); // Only handled case. 1384 ASSERT(constant == kNoConstants); // Only handled case.
1444 1385
1445 // Do combined smi check of the operands. Left operand is on the 1386 // Do combined smi check of the operands. Left operand is on the
1446 // stack (popped into rdx). Right operand is in rax but moved into 1387 // stack (popped into rdx). Right operand is in rax but moved into
1447 // rcx to make the shifts easier. 1388 // rcx to make the shifts easier.
1448 Label done, stub_call, smi_case; 1389 Label done, stub_call, smi_case;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 break; 1431 break;
1491 case Token::BIT_XOR: 1432 case Token::BIT_XOR:
1492 __ SmiXor(rax, rdx, rcx); 1433 __ SmiXor(rax, rdx, rcx);
1493 break; 1434 break;
1494 default: 1435 default:
1495 UNREACHABLE(); 1436 UNREACHABLE();
1496 break; 1437 break;
1497 } 1438 }
1498 1439
1499 __ bind(&done); 1440 __ bind(&done);
1500 Apply(context, rax); 1441 context()->Plug(rax);
1501 } 1442 }
1502 1443
1503 1444
1504 void FullCodeGenerator::EmitBinaryOp(Token::Value op, 1445 void FullCodeGenerator::EmitBinaryOp(Token::Value op,
1505 Expression::Context context,
1506 OverwriteMode mode) { 1446 OverwriteMode mode) {
1507 GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS); 1447 GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS);
1508 if (stub.ArgsInRegistersSupported()) { 1448 if (stub.ArgsInRegistersSupported()) {
1509 __ pop(rdx); 1449 __ pop(rdx);
1510 stub.GenerateCall(masm_, rdx, rax); 1450 stub.GenerateCall(masm_, rdx, rax);
1511 } else { 1451 } else {
1512 __ push(result_register()); 1452 __ push(result_register());
1513 __ CallStub(&stub); 1453 __ CallStub(&stub);
1514 } 1454 }
1515 Apply(context, rax); 1455 context()->Plug(rax);
1516 } 1456 }
1517 1457
1518 1458
1519 void FullCodeGenerator::EmitAssignment(Expression* expr) { 1459 void FullCodeGenerator::EmitAssignment(Expression* expr) {
1520 // Invalid left-hand sides are rewritten to have a 'throw 1460 // Invalid left-hand sides are rewritten to have a 'throw
1521 // ReferenceError' on the left-hand side. 1461 // ReferenceError' on the left-hand side.
1522 if (!expr->IsValidLeftHandSide()) { 1462 if (!expr->IsValidLeftHandSide()) {
1523 VisitForEffect(expr); 1463 VisitForEffect(expr);
1524 return; 1464 return;
1525 } 1465 }
1526 1466
1527 // Left-hand side can only be a property, a global or a (parameter or local) 1467 // Left-hand side can only be a property, a global or a (parameter or local)
1528 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1468 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1529 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1469 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1530 LhsKind assign_type = VARIABLE; 1470 LhsKind assign_type = VARIABLE;
1531 Property* prop = expr->AsProperty(); 1471 Property* prop = expr->AsProperty();
1532 if (prop != NULL) { 1472 if (prop != NULL) {
1533 assign_type = (prop->key()->IsPropertyName()) 1473 assign_type = (prop->key()->IsPropertyName())
1534 ? NAMED_PROPERTY 1474 ? NAMED_PROPERTY
1535 : KEYED_PROPERTY; 1475 : KEYED_PROPERTY;
1536 } 1476 }
1537 1477
1538 switch (assign_type) { 1478 switch (assign_type) {
1539 case VARIABLE: { 1479 case VARIABLE: {
1540 Variable* var = expr->AsVariableProxy()->var(); 1480 Variable* var = expr->AsVariableProxy()->var();
1541 EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); 1481 EffectContext context(this);
1482 EmitVariableAssignment(var, Token::ASSIGN);
1542 break; 1483 break;
1543 } 1484 }
1544 case NAMED_PROPERTY: { 1485 case NAMED_PROPERTY: {
1545 __ push(rax); // Preserve value. 1486 __ push(rax); // Preserve value.
1546 VisitForValue(prop->obj(), kAccumulator); 1487 VisitForAccumulatorValue(prop->obj());
1547 __ movq(rdx, rax); 1488 __ movq(rdx, rax);
1548 __ pop(rax); // Restore value. 1489 __ pop(rax); // Restore value.
1549 __ Move(rcx, prop->key()->AsLiteral()->handle()); 1490 __ Move(rcx, prop->key()->AsLiteral()->handle());
1550 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1491 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1551 __ call(ic, RelocInfo::CODE_TARGET); 1492 __ call(ic, RelocInfo::CODE_TARGET);
1552 __ nop(); // Signal no inlined code. 1493 __ nop(); // Signal no inlined code.
1553 break; 1494 break;
1554 } 1495 }
1555 case KEYED_PROPERTY: { 1496 case KEYED_PROPERTY: {
1556 __ push(rax); // Preserve value. 1497 __ push(rax); // Preserve value.
1557 VisitForValue(prop->obj(), kStack); 1498 VisitForStackValue(prop->obj());
1558 VisitForValue(prop->key(), kAccumulator); 1499 VisitForAccumulatorValue(prop->key());
1559 __ movq(rcx, rax); 1500 __ movq(rcx, rax);
1560 __ pop(rdx); 1501 __ pop(rdx);
1561 __ pop(rax); 1502 __ pop(rax);
1562 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1503 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1563 __ call(ic, RelocInfo::CODE_TARGET); 1504 __ call(ic, RelocInfo::CODE_TARGET);
1564 __ nop(); // Signal no inlined code. 1505 __ nop(); // Signal no inlined code.
1565 break; 1506 break;
1566 } 1507 }
1567 } 1508 }
1568 } 1509 }
1569 1510
1570 1511
1571 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1512 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1572 Token::Value op, 1513 Token::Value op) {
1573 Expression::Context context) {
1574 // Left-hand sides that rewrite to explicit property accesses do not reach 1514 // Left-hand sides that rewrite to explicit property accesses do not reach
1575 // here. 1515 // here.
1576 ASSERT(var != NULL); 1516 ASSERT(var != NULL);
1577 ASSERT(var->is_global() || var->slot() != NULL); 1517 ASSERT(var->is_global() || var->slot() != NULL);
1578 1518
1579 if (var->is_global()) { 1519 if (var->is_global()) {
1580 ASSERT(!var->is_this()); 1520 ASSERT(!var->is_this());
1581 // Assignment to a global variable. Use inline caching for the 1521 // Assignment to a global variable. Use inline caching for the
1582 // assignment. Right-hand-side value is passed in rax, variable name in 1522 // assignment. Right-hand-side value is passed in rax, variable name in
1583 // rcx, and the global object on the stack. 1523 // rcx, and the global object on the stack.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1633 // The runtime will ignore const redeclaration. 1573 // The runtime will ignore const redeclaration.
1634 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1574 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1635 } else { 1575 } else {
1636 __ CallRuntime(Runtime::kStoreContextSlot, 3); 1576 __ CallRuntime(Runtime::kStoreContextSlot, 3);
1637 } 1577 }
1638 break; 1578 break;
1639 } 1579 }
1640 __ bind(&done); 1580 __ bind(&done);
1641 } 1581 }
1642 1582
1643 Apply(context, rax); 1583 context()->Plug(rax);
1644 } 1584 }
1645 1585
1646 1586
1647 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1587 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1648 // Assignment to a property, using a named store IC. 1588 // Assignment to a property, using a named store IC.
1649 Property* prop = expr->target()->AsProperty(); 1589 Property* prop = expr->target()->AsProperty();
1650 ASSERT(prop != NULL); 1590 ASSERT(prop != NULL);
1651 ASSERT(prop->key()->AsLiteral() != NULL); 1591 ASSERT(prop->key()->AsLiteral() != NULL);
1652 1592
1653 // If the assignment starts a block of assignments to the same object, 1593 // If the assignment starts a block of assignments to the same object,
(...skipping 17 matching lines...) Expand all
1671 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1611 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1672 __ Call(ic, RelocInfo::CODE_TARGET); 1612 __ Call(ic, RelocInfo::CODE_TARGET);
1673 __ nop(); 1613 __ nop();
1674 1614
1675 // If the assignment ends an initialization block, revert to fast case. 1615 // If the assignment ends an initialization block, revert to fast case.
1676 if (expr->ends_initialization_block()) { 1616 if (expr->ends_initialization_block()) {
1677 __ push(rax); // Result of assignment, saved even if not needed. 1617 __ push(rax); // Result of assignment, saved even if not needed.
1678 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1618 __ push(Operand(rsp, kPointerSize)); // Receiver is under value.
1679 __ CallRuntime(Runtime::kToFastProperties, 1); 1619 __ CallRuntime(Runtime::kToFastProperties, 1);
1680 __ pop(rax); 1620 __ pop(rax);
1681 DropAndApply(1, context_, rax); 1621 context()->DropAndPlug(1, rax);
1682 } else { 1622 } else {
1683 Apply(context_, rax); 1623 context()->Plug(rax);
1684 } 1624 }
1685 } 1625 }
1686 1626
1687 1627
1688 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1628 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1689 // Assignment to a property, using a keyed store IC. 1629 // Assignment to a property, using a keyed store IC.
1690 1630
1691 // If the assignment starts a block of assignments to the same object, 1631 // If the assignment starts a block of assignments to the same object,
1692 // change to slow case to avoid the quadratic behavior of repeatedly 1632 // change to slow case to avoid the quadratic behavior of repeatedly
1693 // adding fast properties. 1633 // adding fast properties.
(...skipping 21 matching lines...) Expand all
1715 1655
1716 // If the assignment ends an initialization block, revert to fast case. 1656 // If the assignment ends an initialization block, revert to fast case.
1717 if (expr->ends_initialization_block()) { 1657 if (expr->ends_initialization_block()) {
1718 __ pop(rdx); 1658 __ pop(rdx);
1719 __ push(rax); // Result of assignment, saved even if not needed. 1659 __ push(rax); // Result of assignment, saved even if not needed.
1720 __ push(rdx); 1660 __ push(rdx);
1721 __ CallRuntime(Runtime::kToFastProperties, 1); 1661 __ CallRuntime(Runtime::kToFastProperties, 1);
1722 __ pop(rax); 1662 __ pop(rax);
1723 } 1663 }
1724 1664
1725 Apply(context_, rax); 1665 context()->Plug(rax);
1726 } 1666 }
1727 1667
1728 1668
1729 void FullCodeGenerator::VisitProperty(Property* expr) { 1669 void FullCodeGenerator::VisitProperty(Property* expr) {
1730 Comment cmnt(masm_, "[ Property"); 1670 Comment cmnt(masm_, "[ Property");
1731 Expression* key = expr->key(); 1671 Expression* key = expr->key();
1732 1672
1733 if (key->IsPropertyName()) { 1673 if (key->IsPropertyName()) {
1734 VisitForValue(expr->obj(), kAccumulator); 1674 VisitForAccumulatorValue(expr->obj());
1735 EmitNamedPropertyLoad(expr); 1675 EmitNamedPropertyLoad(expr);
1736 Apply(context_, rax); 1676 context()->Plug(rax);
1737 } else { 1677 } else {
1738 VisitForValue(expr->obj(), kStack); 1678 VisitForStackValue(expr->obj());
1739 VisitForValue(expr->key(), kAccumulator); 1679 VisitForAccumulatorValue(expr->key());
1740 __ pop(rdx); 1680 __ pop(rdx);
1741 EmitKeyedPropertyLoad(expr); 1681 EmitKeyedPropertyLoad(expr);
1742 Apply(context_, rax); 1682 context()->Plug(rax);
1743 } 1683 }
1744 } 1684 }
1745 1685
1746 1686
1747 void FullCodeGenerator::EmitCallWithIC(Call* expr, 1687 void FullCodeGenerator::EmitCallWithIC(Call* expr,
1748 Handle<Object> name, 1688 Handle<Object> name,
1749 RelocInfo::Mode mode) { 1689 RelocInfo::Mode mode) {
1750 // Code common for calls using the IC. 1690 // Code common for calls using the IC.
1751 ZoneList<Expression*>* args = expr->arguments(); 1691 ZoneList<Expression*>* args = expr->arguments();
1752 int arg_count = args->length(); 1692 int arg_count = args->length();
1753 for (int i = 0; i < arg_count; i++) { 1693 for (int i = 0; i < arg_count; i++) {
1754 VisitForValue(args->at(i), kStack); 1694 VisitForStackValue(args->at(i));
1755 } 1695 }
1756 __ Move(rcx, name); 1696 __ Move(rcx, name);
1757 // Record source position for debugger. 1697 // Record source position for debugger.
1758 SetSourcePosition(expr->position()); 1698 SetSourcePosition(expr->position());
1759 // Call the IC initialization code. 1699 // Call the IC initialization code.
1760 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1700 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1761 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1701 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1762 in_loop); 1702 in_loop);
1763 __ Call(ic, mode); 1703 __ Call(ic, mode);
1764 // Restore context register. 1704 // Restore context register.
1765 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1705 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1766 Apply(context_, rax); 1706 context()->Plug(rax);
1767 } 1707 }
1768 1708
1769 1709
1770 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 1710 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
1771 Expression* key, 1711 Expression* key,
1772 RelocInfo::Mode mode) { 1712 RelocInfo::Mode mode) {
1773 // Code common for calls using the IC. 1713 // Code common for calls using the IC.
1774 ZoneList<Expression*>* args = expr->arguments(); 1714 ZoneList<Expression*>* args = expr->arguments();
1775 int arg_count = args->length(); 1715 int arg_count = args->length();
1776 for (int i = 0; i < arg_count; i++) { 1716 for (int i = 0; i < arg_count; i++) {
1777 VisitForValue(args->at(i), kStack); 1717 VisitForStackValue(args->at(i));
1778 } 1718 }
1779 VisitForValue(key, kAccumulator); 1719 VisitForAccumulatorValue(key);
1780 __ movq(rcx, rax); 1720 __ movq(rcx, rax);
1781 // Record source position for debugger. 1721 // Record source position for debugger.
1782 SetSourcePosition(expr->position()); 1722 SetSourcePosition(expr->position());
1783 // Call the IC initialization code. 1723 // Call the IC initialization code.
1784 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1724 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1785 Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, 1725 Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
1786 in_loop); 1726 in_loop);
1787 __ Call(ic, mode); 1727 __ Call(ic, mode);
1788 // Restore context register. 1728 // Restore context register.
1789 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1729 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1790 Apply(context_, rax); 1730 context()->Plug(rax);
1791 } 1731 }
1792 1732
1793 1733
1794 void FullCodeGenerator::EmitCallWithStub(Call* expr) { 1734 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
1795 // Code common for calls using the call stub. 1735 // Code common for calls using the call stub.
1796 ZoneList<Expression*>* args = expr->arguments(); 1736 ZoneList<Expression*>* args = expr->arguments();
1797 int arg_count = args->length(); 1737 int arg_count = args->length();
1798 for (int i = 0; i < arg_count; i++) { 1738 for (int i = 0; i < arg_count; i++) {
1799 VisitForValue(args->at(i), kStack); 1739 VisitForStackValue(args->at(i));
1800 } 1740 }
1801 // Record source position for debugger. 1741 // Record source position for debugger.
1802 SetSourcePosition(expr->position()); 1742 SetSourcePosition(expr->position());
1803 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1743 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1804 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1744 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1805 __ CallStub(&stub); 1745 __ CallStub(&stub);
1806 // Restore context register. 1746 // Restore context register.
1807 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1747 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1808 // Discard the function left on TOS. 1748 // Discard the function left on TOS.
1809 DropAndApply(1, context_, rax); 1749 context()->DropAndPlug(1, rax);
1810 } 1750 }
1811 1751
1812 1752
1813 void FullCodeGenerator::VisitCall(Call* expr) { 1753 void FullCodeGenerator::VisitCall(Call* expr) {
1814 Comment cmnt(masm_, "[ Call"); 1754 Comment cmnt(masm_, "[ Call");
1815 Expression* fun = expr->expression(); 1755 Expression* fun = expr->expression();
1816 Variable* var = fun->AsVariableProxy()->AsVariable(); 1756 Variable* var = fun->AsVariableProxy()->AsVariable();
1817 1757
1818 if (var != NULL && var->is_possibly_eval()) { 1758 if (var != NULL && var->is_possibly_eval()) {
1819 // In a call to eval, we first call %ResolvePossiblyDirectEval to 1759 // In a call to eval, we first call %ResolvePossiblyDirectEval to
1820 // resolve the function we need to call and the receiver of the 1760 // resolve the function we need to call and the receiver of the
1821 // call. The we call the resolved function using the given 1761 // call. The we call the resolved function using the given
1822 // arguments. 1762 // arguments.
1823 VisitForValue(fun, kStack); 1763 VisitForStackValue(fun);
1824 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. 1764 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
1825 1765
1826 // Push the arguments. 1766 // Push the arguments.
1827 ZoneList<Expression*>* args = expr->arguments(); 1767 ZoneList<Expression*>* args = expr->arguments();
1828 int arg_count = args->length(); 1768 int arg_count = args->length();
1829 for (int i = 0; i < arg_count; i++) { 1769 for (int i = 0; i < arg_count; i++) {
1830 VisitForValue(args->at(i), kStack); 1770 VisitForStackValue(args->at(i));
1831 } 1771 }
1832 1772
1833 // Push copy of the function - found below the arguments. 1773 // Push copy of the function - found below the arguments.
1834 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); 1774 __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
1835 1775
1836 // Push copy of the first argument or undefined if it doesn't exist. 1776 // Push copy of the first argument or undefined if it doesn't exist.
1837 if (arg_count > 0) { 1777 if (arg_count > 0) {
1838 __ push(Operand(rsp, arg_count * kPointerSize)); 1778 __ push(Operand(rsp, arg_count * kPointerSize));
1839 } else { 1779 } else {
1840 __ PushRoot(Heap::kUndefinedValueRootIndex); 1780 __ PushRoot(Heap::kUndefinedValueRootIndex);
1841 } 1781 }
1842 1782
1843 // Push the receiver of the enclosing function and do runtime call. 1783 // Push the receiver of the enclosing function and do runtime call.
1844 __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); 1784 __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
1845 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); 1785 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
1846 1786
1847 // The runtime call returns a pair of values in rax (function) and 1787 // The runtime call returns a pair of values in rax (function) and
1848 // rdx (receiver). Touch up the stack with the right values. 1788 // rdx (receiver). Touch up the stack with the right values.
1849 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); 1789 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
1850 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); 1790 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
1851 1791
1852 // Record source position for debugger. 1792 // Record source position for debugger.
1853 SetSourcePosition(expr->position()); 1793 SetSourcePosition(expr->position());
1854 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1794 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1855 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1795 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1856 __ CallStub(&stub); 1796 __ CallStub(&stub);
1857 // Restore context register. 1797 // Restore context register.
1858 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1798 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1859 DropAndApply(1, context_, rax); 1799 context()->DropAndPlug(1, rax);
1860 } else if (var != NULL && !var->is_this() && var->is_global()) { 1800 } else if (var != NULL && !var->is_this() && var->is_global()) {
1861 // Call to a global variable. 1801 // Call to a global variable.
1862 // Push global object as receiver for the call IC lookup. 1802 // Push global object as receiver for the call IC lookup.
1863 __ push(CodeGenerator::GlobalObject()); 1803 __ push(CodeGenerator::GlobalObject());
1864 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1804 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1865 } else if (var != NULL && var->slot() != NULL && 1805 } else if (var != NULL && var->slot() != NULL &&
1866 var->slot()->type() == Slot::LOOKUP) { 1806 var->slot()->type() == Slot::LOOKUP) {
1867 // Call to a lookup slot (dynamically introduced variable). 1807 // Call to a lookup slot (dynamically introduced variable).
1868 Label slow, done; 1808 Label slow, done;
1869 1809
(...skipping 29 matching lines...) Expand all
1899 } 1839 }
1900 1840
1901 EmitCallWithStub(expr); 1841 EmitCallWithStub(expr);
1902 1842
1903 } else if (fun->AsProperty() != NULL) { 1843 } else if (fun->AsProperty() != NULL) {
1904 // Call to an object property. 1844 // Call to an object property.
1905 Property* prop = fun->AsProperty(); 1845 Property* prop = fun->AsProperty();
1906 Literal* key = prop->key()->AsLiteral(); 1846 Literal* key = prop->key()->AsLiteral();
1907 if (key != NULL && key->handle()->IsSymbol()) { 1847 if (key != NULL && key->handle()->IsSymbol()) {
1908 // Call to a named property, use call IC. 1848 // Call to a named property, use call IC.
1909 VisitForValue(prop->obj(), kStack); 1849 VisitForStackValue(prop->obj());
1910 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1850 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1911 } else { 1851 } else {
1912 // Call to a keyed property. 1852 // Call to a keyed property.
1913 // For a synthetic property use keyed load IC followed by function call, 1853 // For a synthetic property use keyed load IC followed by function call,
1914 // for a regular property use KeyedCallIC. 1854 // for a regular property use KeyedCallIC.
1915 VisitForValue(prop->obj(), kStack); 1855 VisitForStackValue(prop->obj());
1916 if (prop->is_synthetic()) { 1856 if (prop->is_synthetic()) {
1917 VisitForValue(prop->key(), kAccumulator); 1857 VisitForAccumulatorValue(prop->key());
1918 __ movq(rdx, Operand(rsp, 0)); 1858 __ movq(rdx, Operand(rsp, 0));
1919 // Record source code position for IC call. 1859 // Record source code position for IC call.
1920 SetSourcePosition(prop->position()); 1860 SetSourcePosition(prop->position());
1921 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1861 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1922 __ call(ic, RelocInfo::CODE_TARGET); 1862 __ call(ic, RelocInfo::CODE_TARGET);
1923 // By emitting a nop we make sure that we do not have a "test rax,..." 1863 // By emitting a nop we make sure that we do not have a "test rax,..."
1924 // instruction after the call as it is treated specially 1864 // instruction after the call as it is treated specially
1925 // by the LoadIC code. 1865 // by the LoadIC code.
1926 __ nop(); 1866 __ nop();
1927 // Pop receiver. 1867 // Pop receiver.
(...skipping 11 matching lines...) Expand all
1939 } else { 1879 } else {
1940 // Call to some other expression. If the expression is an anonymous 1880 // Call to some other expression. If the expression is an anonymous
1941 // function literal not called in a loop, mark it as one that should 1881 // function literal not called in a loop, mark it as one that should
1942 // also use the fast code generator. 1882 // also use the fast code generator.
1943 FunctionLiteral* lit = fun->AsFunctionLiteral(); 1883 FunctionLiteral* lit = fun->AsFunctionLiteral();
1944 if (lit != NULL && 1884 if (lit != NULL &&
1945 lit->name()->Equals(Heap::empty_string()) && 1885 lit->name()->Equals(Heap::empty_string()) &&
1946 loop_depth() == 0) { 1886 loop_depth() == 0) {
1947 lit->set_try_full_codegen(true); 1887 lit->set_try_full_codegen(true);
1948 } 1888 }
1949 VisitForValue(fun, kStack); 1889 VisitForStackValue(fun);
1950 // Load global receiver object. 1890 // Load global receiver object.
1951 __ movq(rbx, CodeGenerator::GlobalObject()); 1891 __ movq(rbx, CodeGenerator::GlobalObject());
1952 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 1892 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
1953 // Emit function call. 1893 // Emit function call.
1954 EmitCallWithStub(expr); 1894 EmitCallWithStub(expr);
1955 } 1895 }
1956 } 1896 }
1957 1897
1958 1898
1959 void FullCodeGenerator::VisitCallNew(CallNew* expr) { 1899 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
1960 Comment cmnt(masm_, "[ CallNew"); 1900 Comment cmnt(masm_, "[ CallNew");
1961 // According to ECMA-262, section 11.2.2, page 44, the function 1901 // According to ECMA-262, section 11.2.2, page 44, the function
1962 // expression in new calls must be evaluated before the 1902 // expression in new calls must be evaluated before the
1963 // arguments. 1903 // arguments.
1964 1904
1965 // Push constructor on the stack. If it's not a function it's used as 1905 // Push constructor on the stack. If it's not a function it's used as
1966 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 1906 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
1967 // ignored. 1907 // ignored.
1968 VisitForValue(expr->expression(), kStack); 1908 VisitForStackValue(expr->expression());
1969 1909
1970 // Push the arguments ("left-to-right") on the stack. 1910 // Push the arguments ("left-to-right") on the stack.
1971 ZoneList<Expression*>* args = expr->arguments(); 1911 ZoneList<Expression*>* args = expr->arguments();
1972 int arg_count = args->length(); 1912 int arg_count = args->length();
1973 for (int i = 0; i < arg_count; i++) { 1913 for (int i = 0; i < arg_count; i++) {
1974 VisitForValue(args->at(i), kStack); 1914 VisitForStackValue(args->at(i));
1975 } 1915 }
1976 1916
1977 // Call the construct call builtin that handles allocation and 1917 // Call the construct call builtin that handles allocation and
1978 // constructor invocation. 1918 // constructor invocation.
1979 SetSourcePosition(expr->position()); 1919 SetSourcePosition(expr->position());
1980 1920
1981 // Load function and argument count into rdi and rax. 1921 // Load function and argument count into rdi and rax.
1982 __ Set(rax, arg_count); 1922 __ Set(rax, arg_count);
1983 __ movq(rdi, Operand(rsp, arg_count * kPointerSize)); 1923 __ movq(rdi, Operand(rsp, arg_count * kPointerSize));
1984 1924
1985 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1925 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1986 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 1926 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
1987 Apply(context_, rax); 1927 context()->Plug(rax);
1988 } 1928 }
1989 1929
1990 1930
1991 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 1931 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
1992 ASSERT(args->length() == 1); 1932 ASSERT(args->length() == 1);
1993 1933
1994 VisitForValue(args->at(0), kAccumulator); 1934 VisitForAccumulatorValue(args->at(0));
1995 1935
1996 Label materialize_true, materialize_false; 1936 Label materialize_true, materialize_false;
1997 Label* if_true = NULL; 1937 Label* if_true = NULL;
1998 Label* if_false = NULL; 1938 Label* if_false = NULL;
1999 Label* fall_through = NULL; 1939 Label* fall_through = NULL;
2000 PrepareTest(&materialize_true, &materialize_false, 1940 context()->PrepareTest(&materialize_true, &materialize_false,
2001 &if_true, &if_false, &fall_through); 1941 &if_true, &if_false, &fall_through);
2002 1942
2003 __ JumpIfSmi(rax, if_true); 1943 __ JumpIfSmi(rax, if_true);
2004 __ jmp(if_false); 1944 __ jmp(if_false);
2005 1945
2006 Apply(context_, if_true, if_false); 1946 context()->Plug(if_true, if_false);
2007 } 1947 }
2008 1948
2009 1949
2010 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 1950 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
2011 ASSERT(args->length() == 1); 1951 ASSERT(args->length() == 1);
2012 1952
2013 VisitForValue(args->at(0), kAccumulator); 1953 VisitForAccumulatorValue(args->at(0));
2014 1954
2015 Label materialize_true, materialize_false; 1955 Label materialize_true, materialize_false;
2016 Label* if_true = NULL; 1956 Label* if_true = NULL;
2017 Label* if_false = NULL; 1957 Label* if_false = NULL;
2018 Label* fall_through = NULL; 1958 Label* fall_through = NULL;
2019 PrepareTest(&materialize_true, &materialize_false, 1959 context()->PrepareTest(&materialize_true, &materialize_false,
2020 &if_true, &if_false, &fall_through); 1960 &if_true, &if_false, &fall_through);
2021 1961
2022 Condition positive_smi = __ CheckPositiveSmi(rax); 1962 Condition positive_smi = __ CheckPositiveSmi(rax);
2023 Split(positive_smi, if_true, if_false, fall_through); 1963 Split(positive_smi, if_true, if_false, fall_through);
2024 1964
2025 Apply(context_, if_true, if_false); 1965 context()->Plug(if_true, if_false);
2026 } 1966 }
2027 1967
2028 1968
2029 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 1969 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
2030 ASSERT(args->length() == 1); 1970 ASSERT(args->length() == 1);
2031 1971
2032 VisitForValue(args->at(0), kAccumulator); 1972 VisitForAccumulatorValue(args->at(0));
2033 1973
2034 Label materialize_true, materialize_false; 1974 Label materialize_true, materialize_false;
2035 Label* if_true = NULL; 1975 Label* if_true = NULL;
2036 Label* if_false = NULL; 1976 Label* if_false = NULL;
2037 Label* fall_through = NULL; 1977 Label* fall_through = NULL;
2038 PrepareTest(&materialize_true, &materialize_false, 1978 context()->PrepareTest(&materialize_true, &materialize_false,
2039 &if_true, &if_false, &fall_through); 1979 &if_true, &if_false, &fall_through);
2040 1980
2041 __ JumpIfSmi(rax, if_false); 1981 __ JumpIfSmi(rax, if_false);
2042 __ CompareRoot(rax, Heap::kNullValueRootIndex); 1982 __ CompareRoot(rax, Heap::kNullValueRootIndex);
2043 __ j(equal, if_true); 1983 __ j(equal, if_true);
2044 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 1984 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2045 // Undetectable objects behave like undefined when tested with typeof. 1985 // Undetectable objects behave like undefined when tested with typeof.
2046 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 1986 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2047 Immediate(1 << Map::kIsUndetectable)); 1987 Immediate(1 << Map::kIsUndetectable));
2048 __ j(not_zero, if_false); 1988 __ j(not_zero, if_false);
2049 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 1989 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2050 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); 1990 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE));
2051 __ j(below, if_false); 1991 __ j(below, if_false);
2052 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); 1992 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE));
2053 Split(below_equal, if_true, if_false, fall_through); 1993 Split(below_equal, if_true, if_false, fall_through);
2054 1994
2055 Apply(context_, if_true, if_false); 1995 context()->Plug(if_true, if_false);
2056 } 1996 }
2057 1997
2058 1998
2059 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 1999 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
2060 ASSERT(args->length() == 1); 2000 ASSERT(args->length() == 1);
2061 2001
2062 VisitForValue(args->at(0), kAccumulator); 2002 VisitForAccumulatorValue(args->at(0));
2063 2003
2064 Label materialize_true, materialize_false; 2004 Label materialize_true, materialize_false;
2065 Label* if_true = NULL; 2005 Label* if_true = NULL;
2066 Label* if_false = NULL; 2006 Label* if_false = NULL;
2067 Label* fall_through = NULL; 2007 Label* fall_through = NULL;
2068 PrepareTest(&materialize_true, &materialize_false, 2008 context()->PrepareTest(&materialize_true, &materialize_false,
2069 &if_true, &if_false, &fall_through); 2009 &if_true, &if_false, &fall_through);
2070 2010
2071 __ JumpIfSmi(rax, if_false); 2011 __ JumpIfSmi(rax, if_false);
2072 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); 2012 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
2073 Split(above_equal, if_true, if_false, fall_through); 2013 Split(above_equal, if_true, if_false, fall_through);
2074 2014
2075 Apply(context_, if_true, if_false); 2015 context()->Plug(if_true, if_false);
2076 } 2016 }
2077 2017
2078 2018
2079 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2019 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2080 ASSERT(args->length() == 1); 2020 ASSERT(args->length() == 1);
2081 2021
2082 VisitForValue(args->at(0), kAccumulator); 2022 VisitForAccumulatorValue(args->at(0));
2083 2023
2084 Label materialize_true, materialize_false; 2024 Label materialize_true, materialize_false;
2085 Label* if_true = NULL; 2025 Label* if_true = NULL;
2086 Label* if_false = NULL; 2026 Label* if_false = NULL;
2087 Label* fall_through = NULL; 2027 Label* fall_through = NULL;
2088 PrepareTest(&materialize_true, &materialize_false, 2028 context()->PrepareTest(&materialize_true, &materialize_false,
2089 &if_true, &if_false, &fall_through); 2029 &if_true, &if_false, &fall_through);
2090 2030
2091 __ JumpIfSmi(rax, if_false); 2031 __ JumpIfSmi(rax, if_false);
2092 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2032 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2093 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2033 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2094 Immediate(1 << Map::kIsUndetectable)); 2034 Immediate(1 << Map::kIsUndetectable));
2095 Split(not_zero, if_true, if_false, fall_through); 2035 Split(not_zero, if_true, if_false, fall_through);
2096 2036
2097 Apply(context_, if_true, if_false); 2037 context()->Plug(if_true, if_false);
2098 } 2038 }
2099 2039
2100 2040
2101 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2041 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2102 ZoneList<Expression*>* args) { 2042 ZoneList<Expression*>* args) {
2103 ASSERT(args->length() == 1); 2043 ASSERT(args->length() == 1);
2104 2044
2105 VisitForValue(args->at(0), kAccumulator); 2045 VisitForAccumulatorValue(args->at(0));
2106 2046
2107 Label materialize_true, materialize_false; 2047 Label materialize_true, materialize_false;
2108 Label* if_true = NULL; 2048 Label* if_true = NULL;
2109 Label* if_false = NULL; 2049 Label* if_false = NULL;
2110 Label* fall_through = NULL; 2050 Label* fall_through = NULL;
2111 PrepareTest(&materialize_true, &materialize_false, 2051 context()->PrepareTest(&materialize_true, &materialize_false,
2112 &if_true, &if_false, &fall_through); 2052 &if_true, &if_false, &fall_through);
2113 2053
2114 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only 2054 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
2115 // used in a few functions in runtime.js which should not normally be hit by 2055 // used in a few functions in runtime.js which should not normally be hit by
2116 // this compiler. 2056 // this compiler.
2117 __ jmp(if_false); 2057 __ jmp(if_false);
2118 Apply(context_, if_true, if_false); 2058 context()->Plug(if_true, if_false);
2119 } 2059 }
2120 2060
2121 2061
2122 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2062 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2123 ASSERT(args->length() == 1); 2063 ASSERT(args->length() == 1);
2124 2064
2125 VisitForValue(args->at(0), kAccumulator); 2065 VisitForAccumulatorValue(args->at(0));
2126 2066
2127 Label materialize_true, materialize_false; 2067 Label materialize_true, materialize_false;
2128 Label* if_true = NULL; 2068 Label* if_true = NULL;
2129 Label* if_false = NULL; 2069 Label* if_false = NULL;
2130 Label* fall_through = NULL; 2070 Label* fall_through = NULL;
2131 PrepareTest(&materialize_true, &materialize_false, 2071 context()->PrepareTest(&materialize_true, &materialize_false,
2132 &if_true, &if_false, &fall_through); 2072 &if_true, &if_false, &fall_through);
2133 2073
2134 __ JumpIfSmi(rax, if_false); 2074 __ JumpIfSmi(rax, if_false);
2135 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2075 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2136 Split(equal, if_true, if_false, fall_through); 2076 Split(equal, if_true, if_false, fall_through);
2137 2077
2138 Apply(context_, if_true, if_false); 2078 context()->Plug(if_true, if_false);
2139 } 2079 }
2140 2080
2141 2081
2142 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2082 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2143 ASSERT(args->length() == 1); 2083 ASSERT(args->length() == 1);
2144 2084
2145 VisitForValue(args->at(0), kAccumulator); 2085 VisitForAccumulatorValue(args->at(0));
2146 2086
2147 Label materialize_true, materialize_false; 2087 Label materialize_true, materialize_false;
2148 Label* if_true = NULL; 2088 Label* if_true = NULL;
2149 Label* if_false = NULL; 2089 Label* if_false = NULL;
2150 Label* fall_through = NULL; 2090 Label* fall_through = NULL;
2151 PrepareTest(&materialize_true, &materialize_false, 2091 context()->PrepareTest(&materialize_true, &materialize_false,
2152 &if_true, &if_false, &fall_through); 2092 &if_true, &if_false, &fall_through);
2153 2093
2154 __ JumpIfSmi(rax, if_false); 2094 __ JumpIfSmi(rax, if_false);
2155 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); 2095 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
2156 Split(equal, if_true, if_false, fall_through); 2096 Split(equal, if_true, if_false, fall_through);
2157 2097
2158 Apply(context_, if_true, if_false); 2098 context()->Plug(if_true, if_false);
2159 } 2099 }
2160 2100
2161 2101
2162 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2102 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2163 ASSERT(args->length() == 1); 2103 ASSERT(args->length() == 1);
2164 2104
2165 VisitForValue(args->at(0), kAccumulator); 2105 VisitForAccumulatorValue(args->at(0));
2166 2106
2167 Label materialize_true, materialize_false; 2107 Label materialize_true, materialize_false;
2168 Label* if_true = NULL; 2108 Label* if_true = NULL;
2169 Label* if_false = NULL; 2109 Label* if_false = NULL;
2170 Label* fall_through = NULL; 2110 Label* fall_through = NULL;
2171 PrepareTest(&materialize_true, &materialize_false, 2111 context()->PrepareTest(&materialize_true, &materialize_false,
2172 &if_true, &if_false, &fall_through); 2112 &if_true, &if_false, &fall_through);
2173 2113
2174 __ JumpIfSmi(rax, if_false); 2114 __ JumpIfSmi(rax, if_false);
2175 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); 2115 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
2176 Split(equal, if_true, if_false, fall_through); 2116 Split(equal, if_true, if_false, fall_through);
2177 2117
2178 Apply(context_, if_true, if_false); 2118 context()->Plug(if_true, if_false);
2179 } 2119 }
2180 2120
2181 2121
2182 2122
2183 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2123 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2184 ASSERT(args->length() == 0); 2124 ASSERT(args->length() == 0);
2185 2125
2186 Label materialize_true, materialize_false; 2126 Label materialize_true, materialize_false;
2187 Label* if_true = NULL; 2127 Label* if_true = NULL;
2188 Label* if_false = NULL; 2128 Label* if_false = NULL;
2189 Label* fall_through = NULL; 2129 Label* fall_through = NULL;
2190 PrepareTest(&materialize_true, &materialize_false, 2130 context()->PrepareTest(&materialize_true, &materialize_false,
2191 &if_true, &if_false, &fall_through); 2131 &if_true, &if_false, &fall_through);
2192 2132
2193 // Get the frame pointer for the calling frame. 2133 // Get the frame pointer for the calling frame.
2194 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2134 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2195 2135
2196 // Skip the arguments adaptor frame if it exists. 2136 // Skip the arguments adaptor frame if it exists.
2197 Label check_frame_marker; 2137 Label check_frame_marker;
2198 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), 2138 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset),
2199 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2139 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2200 __ j(not_equal, &check_frame_marker); 2140 __ j(not_equal, &check_frame_marker);
2201 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 2141 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2202 2142
2203 // Check the marker in the calling frame. 2143 // Check the marker in the calling frame.
2204 __ bind(&check_frame_marker); 2144 __ bind(&check_frame_marker);
2205 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), 2145 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset),
2206 Smi::FromInt(StackFrame::CONSTRUCT)); 2146 Smi::FromInt(StackFrame::CONSTRUCT));
2207 Split(equal, if_true, if_false, fall_through); 2147 Split(equal, if_true, if_false, fall_through);
2208 2148
2209 Apply(context_, if_true, if_false); 2149 context()->Plug(if_true, if_false);
2210 } 2150 }
2211 2151
2212 2152
2213 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2153 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2214 ASSERT(args->length() == 2); 2154 ASSERT(args->length() == 2);
2215 2155
2216 // Load the two objects into registers and perform the comparison. 2156 // Load the two objects into registers and perform the comparison.
2217 VisitForValue(args->at(0), kStack); 2157 VisitForStackValue(args->at(0));
2218 VisitForValue(args->at(1), kAccumulator); 2158 VisitForAccumulatorValue(args->at(1));
2219 2159
2220 Label materialize_true, materialize_false; 2160 Label materialize_true, materialize_false;
2221 Label* if_true = NULL; 2161 Label* if_true = NULL;
2222 Label* if_false = NULL; 2162 Label* if_false = NULL;
2223 Label* fall_through = NULL; 2163 Label* fall_through = NULL;
2224 PrepareTest(&materialize_true, &materialize_false, 2164 context()->PrepareTest(&materialize_true, &materialize_false,
2225 &if_true, &if_false, &fall_through); 2165 &if_true, &if_false, &fall_through);
2226 2166
2227 __ pop(rbx); 2167 __ pop(rbx);
2228 __ cmpq(rax, rbx); 2168 __ cmpq(rax, rbx);
2229 Split(equal, if_true, if_false, fall_through); 2169 Split(equal, if_true, if_false, fall_through);
2230 2170
2231 Apply(context_, if_true, if_false); 2171 context()->Plug(if_true, if_false);
2232 } 2172 }
2233 2173
2234 2174
2235 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2175 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2236 ASSERT(args->length() == 1); 2176 ASSERT(args->length() == 1);
2237 2177
2238 // ArgumentsAccessStub expects the key in rdx and the formal 2178 // ArgumentsAccessStub expects the key in rdx and the formal
2239 // parameter count in rax. 2179 // parameter count in rax.
2240 VisitForValue(args->at(0), kAccumulator); 2180 VisitForAccumulatorValue(args->at(0));
2241 __ movq(rdx, rax); 2181 __ movq(rdx, rax);
2242 __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2182 __ Move(rax, Smi::FromInt(scope()->num_parameters()));
2243 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2183 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2244 __ CallStub(&stub); 2184 __ CallStub(&stub);
2245 Apply(context_, rax); 2185 context()->Plug(rax);
2246 } 2186 }
2247 2187
2248 2188
2249 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2189 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2250 ASSERT(args->length() == 0); 2190 ASSERT(args->length() == 0);
2251 2191
2252 Label exit; 2192 Label exit;
2253 // Get the number of formal parameters. 2193 // Get the number of formal parameters.
2254 __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2194 __ Move(rax, Smi::FromInt(scope()->num_parameters()));
2255 2195
2256 // Check if the calling frame is an arguments adaptor frame. 2196 // Check if the calling frame is an arguments adaptor frame.
2257 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2197 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2258 __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset), 2198 __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset),
2259 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2199 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2260 __ j(not_equal, &exit); 2200 __ j(not_equal, &exit);
2261 2201
2262 // Arguments adaptor case: Read the arguments length from the 2202 // Arguments adaptor case: Read the arguments length from the
2263 // adaptor frame. 2203 // adaptor frame.
2264 __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2204 __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2265 2205
2266 __ bind(&exit); 2206 __ bind(&exit);
2267 if (FLAG_debug_code) __ AbortIfNotSmi(rax); 2207 if (FLAG_debug_code) __ AbortIfNotSmi(rax);
2268 Apply(context_, rax); 2208 context()->Plug(rax);
2269 } 2209 }
2270 2210
2271 2211
2272 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2212 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2273 ASSERT(args->length() == 1); 2213 ASSERT(args->length() == 1);
2274 Label done, null, function, non_function_constructor; 2214 Label done, null, function, non_function_constructor;
2275 2215
2276 VisitForValue(args->at(0), kAccumulator); 2216 VisitForAccumulatorValue(args->at(0));
2277 2217
2278 // If the object is a smi, we return null. 2218 // If the object is a smi, we return null.
2279 __ JumpIfSmi(rax, &null); 2219 __ JumpIfSmi(rax, &null);
2280 2220
2281 // Check that the object is a JS object but take special care of JS 2221 // Check that the object is a JS object but take special care of JS
2282 // functions to make sure they have 'Function' as their class. 2222 // functions to make sure they have 'Function' as their class.
2283 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax); // Map is now in rax. 2223 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax); // Map is now in rax.
2284 __ j(below, &null); 2224 __ j(below, &null);
2285 2225
2286 // As long as JS_FUNCTION_TYPE is the last instance type and it is 2226 // As long as JS_FUNCTION_TYPE is the last instance type and it is
(...skipping 25 matching lines...) Expand all
2312 __ Move(rax, Factory::Object_symbol()); 2252 __ Move(rax, Factory::Object_symbol());
2313 __ jmp(&done); 2253 __ jmp(&done);
2314 2254
2315 // Non-JS objects have class null. 2255 // Non-JS objects have class null.
2316 __ bind(&null); 2256 __ bind(&null);
2317 __ LoadRoot(rax, Heap::kNullValueRootIndex); 2257 __ LoadRoot(rax, Heap::kNullValueRootIndex);
2318 2258
2319 // All done. 2259 // All done.
2320 __ bind(&done); 2260 __ bind(&done);
2321 2261
2322 Apply(context_, rax); 2262 context()->Plug(rax);
2323 } 2263 }
2324 2264
2325 2265
2326 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2266 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
2327 // Conditionally generate a log call. 2267 // Conditionally generate a log call.
2328 // Args: 2268 // Args:
2329 // 0 (literal string): The type of logging (corresponds to the flags). 2269 // 0 (literal string): The type of logging (corresponds to the flags).
2330 // This is used to determine whether or not to generate the log call. 2270 // This is used to determine whether or not to generate the log call.
2331 // 1 (string): Format string. Access the string at argument index 2 2271 // 1 (string): Format string. Access the string at argument index 2
2332 // with '%2s' (see Logger::LogRuntime for all the formats). 2272 // with '%2s' (see Logger::LogRuntime for all the formats).
2333 // 2 (array): Arguments to the format string. 2273 // 2 (array): Arguments to the format string.
2334 ASSERT_EQ(args->length(), 3); 2274 ASSERT_EQ(args->length(), 3);
2335 #ifdef ENABLE_LOGGING_AND_PROFILING 2275 #ifdef ENABLE_LOGGING_AND_PROFILING
2336 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 2276 if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2337 VisitForValue(args->at(1), kStack); 2277 VisitForStackValue(args->at(1));
2338 VisitForValue(args->at(2), kStack); 2278 VisitForStackValue(args->at(2));
2339 __ CallRuntime(Runtime::kLog, 2); 2279 __ CallRuntime(Runtime::kLog, 2);
2340 } 2280 }
2341 #endif 2281 #endif
2342 // Finally, we're expected to leave a value on the top of the stack. 2282 // Finally, we're expected to leave a value on the top of the stack.
2343 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2283 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2344 Apply(context_, rax); 2284 context()->Plug(rax);
2345 } 2285 }
2346 2286
2347 2287
2348 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2288 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
2349 ASSERT(args->length() == 0); 2289 ASSERT(args->length() == 0);
2350 2290
2351 Label slow_allocate_heapnumber; 2291 Label slow_allocate_heapnumber;
2352 Label heapnumber_allocated; 2292 Label heapnumber_allocated;
2353 2293
2354 __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber); 2294 __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber);
(...skipping 16 matching lines...) Expand all
2371 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2311 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2372 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 2312 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
2373 __ movd(xmm1, rcx); 2313 __ movd(xmm1, rcx);
2374 __ movd(xmm0, rax); 2314 __ movd(xmm0, rax);
2375 __ cvtss2sd(xmm1, xmm1); 2315 __ cvtss2sd(xmm1, xmm1);
2376 __ xorpd(xmm0, xmm1); 2316 __ xorpd(xmm0, xmm1);
2377 __ subsd(xmm0, xmm1); 2317 __ subsd(xmm0, xmm1);
2378 __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0); 2318 __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0);
2379 2319
2380 __ movq(rax, rbx); 2320 __ movq(rax, rbx);
2381 Apply(context_, rax); 2321 context()->Plug(rax);
2382 } 2322 }
2383 2323
2384 2324
2385 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2325 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2386 // Load the arguments on the stack and call the stub. 2326 // Load the arguments on the stack and call the stub.
2387 SubStringStub stub; 2327 SubStringStub stub;
2388 ASSERT(args->length() == 3); 2328 ASSERT(args->length() == 3);
2389 VisitForValue(args->at(0), kStack); 2329 VisitForStackValue(args->at(0));
2390 VisitForValue(args->at(1), kStack); 2330 VisitForStackValue(args->at(1));
2391 VisitForValue(args->at(2), kStack); 2331 VisitForStackValue(args->at(2));
2392 __ CallStub(&stub); 2332 __ CallStub(&stub);
2393 Apply(context_, rax); 2333 context()->Plug(rax);
2394 } 2334 }
2395 2335
2396 2336
2397 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2337 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2398 // Load the arguments on the stack and call the stub. 2338 // Load the arguments on the stack and call the stub.
2399 RegExpExecStub stub; 2339 RegExpExecStub stub;
2400 ASSERT(args->length() == 4); 2340 ASSERT(args->length() == 4);
2401 VisitForValue(args->at(0), kStack); 2341 VisitForStackValue(args->at(0));
2402 VisitForValue(args->at(1), kStack); 2342 VisitForStackValue(args->at(1));
2403 VisitForValue(args->at(2), kStack); 2343 VisitForStackValue(args->at(2));
2404 VisitForValue(args->at(3), kStack); 2344 VisitForStackValue(args->at(3));
2405 __ CallStub(&stub); 2345 __ CallStub(&stub);
2406 Apply(context_, rax); 2346 context()->Plug(rax);
2407 } 2347 }
2408 2348
2409 2349
2410 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2350 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2411 ASSERT(args->length() == 1); 2351 ASSERT(args->length() == 1);
2412 2352
2413 VisitForValue(args->at(0), kAccumulator); // Load the object. 2353 VisitForAccumulatorValue(args->at(0)); // Load the object.
2414 2354
2415 Label done; 2355 Label done;
2416 // If the object is a smi return the object. 2356 // If the object is a smi return the object.
2417 __ JumpIfSmi(rax, &done); 2357 __ JumpIfSmi(rax, &done);
2418 // If the object is not a value type, return the object. 2358 // If the object is not a value type, return the object.
2419 __ CmpObjectType(rax, JS_VALUE_TYPE, rbx); 2359 __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
2420 __ j(not_equal, &done); 2360 __ j(not_equal, &done);
2421 __ movq(rax, FieldOperand(rax, JSValue::kValueOffset)); 2361 __ movq(rax, FieldOperand(rax, JSValue::kValueOffset));
2422 2362
2423 __ bind(&done); 2363 __ bind(&done);
2424 Apply(context_, rax); 2364 context()->Plug(rax);
2425 } 2365 }
2426 2366
2427 2367
2428 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2368 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2429 // Load the arguments on the stack and call the runtime function. 2369 // Load the arguments on the stack and call the runtime function.
2430 ASSERT(args->length() == 2); 2370 ASSERT(args->length() == 2);
2431 VisitForValue(args->at(0), kStack); 2371 VisitForStackValue(args->at(0));
2432 VisitForValue(args->at(1), kStack); 2372 VisitForStackValue(args->at(1));
2433 __ CallRuntime(Runtime::kMath_pow, 2); 2373 __ CallRuntime(Runtime::kMath_pow, 2);
2434 Apply(context_, rax); 2374 context()->Plug(rax);
2435 } 2375 }
2436 2376
2437 2377
2438 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2378 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2439 ASSERT(args->length() == 2); 2379 ASSERT(args->length() == 2);
2440 2380
2441 VisitForValue(args->at(0), kStack); // Load the object. 2381 VisitForStackValue(args->at(0)); // Load the object.
2442 VisitForValue(args->at(1), kAccumulator); // Load the value. 2382 VisitForAccumulatorValue(args->at(1)); // Load the value.
2443 __ pop(rbx); // rax = value. rbx = object. 2383 __ pop(rbx); // rax = value. rbx = object.
2444 2384
2445 Label done; 2385 Label done;
2446 // If the object is a smi, return the value. 2386 // If the object is a smi, return the value.
2447 __ JumpIfSmi(rbx, &done); 2387 __ JumpIfSmi(rbx, &done);
2448 2388
2449 // If the object is not a value type, return the value. 2389 // If the object is not a value type, return the value.
2450 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); 2390 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
2451 __ j(not_equal, &done); 2391 __ j(not_equal, &done);
2452 2392
2453 // Store the value. 2393 // Store the value.
2454 __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax); 2394 __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax);
2455 // Update the write barrier. Save the value as it will be 2395 // Update the write barrier. Save the value as it will be
2456 // overwritten by the write barrier code and is needed afterward. 2396 // overwritten by the write barrier code and is needed afterward.
2457 __ movq(rdx, rax); 2397 __ movq(rdx, rax);
2458 __ RecordWrite(rbx, JSValue::kValueOffset, rdx, rcx); 2398 __ RecordWrite(rbx, JSValue::kValueOffset, rdx, rcx);
2459 2399
2460 __ bind(&done); 2400 __ bind(&done);
2461 Apply(context_, rax); 2401 context()->Plug(rax);
2462 } 2402 }
2463 2403
2464 2404
2465 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2405 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2466 ASSERT_EQ(args->length(), 1); 2406 ASSERT_EQ(args->length(), 1);
2467 2407
2468 // Load the argument on the stack and call the stub. 2408 // Load the argument on the stack and call the stub.
2469 VisitForValue(args->at(0), kStack); 2409 VisitForStackValue(args->at(0));
2470 2410
2471 NumberToStringStub stub; 2411 NumberToStringStub stub;
2472 __ CallStub(&stub); 2412 __ CallStub(&stub);
2473 Apply(context_, rax); 2413 context()->Plug(rax);
2474 } 2414 }
2475 2415
2476 2416
2477 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2417 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
2478 ASSERT(args->length() == 1); 2418 ASSERT(args->length() == 1);
2479 2419
2480 VisitForValue(args->at(0), kAccumulator); 2420 VisitForAccumulatorValue(args->at(0));
2481 2421
2482 Label done; 2422 Label done;
2483 StringCharFromCodeGenerator generator(rax, rbx); 2423 StringCharFromCodeGenerator generator(rax, rbx);
2484 generator.GenerateFast(masm_); 2424 generator.GenerateFast(masm_);
2485 __ jmp(&done); 2425 __ jmp(&done);
2486 2426
2487 NopRuntimeCallHelper call_helper; 2427 NopRuntimeCallHelper call_helper;
2488 generator.GenerateSlow(masm_, call_helper); 2428 generator.GenerateSlow(masm_, call_helper);
2489 2429
2490 __ bind(&done); 2430 __ bind(&done);
2491 Apply(context_, rbx); 2431 context()->Plug(rbx);
2492 } 2432 }
2493 2433
2494 2434
2495 void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 2435 void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
2496 ASSERT(args->length() == 2); 2436 ASSERT(args->length() == 2);
2497 2437
2498 VisitForValue(args->at(0), kStack); 2438 VisitForStackValue(args->at(0));
2499 VisitForValue(args->at(1), kAccumulator); 2439 VisitForAccumulatorValue(args->at(1));
2500 2440
2501 Register object = rbx; 2441 Register object = rbx;
2502 Register index = rax; 2442 Register index = rax;
2503 Register scratch = rcx; 2443 Register scratch = rcx;
2504 Register result = rdx; 2444 Register result = rdx;
2505 2445
2506 __ pop(object); 2446 __ pop(object);
2507 2447
2508 Label need_conversion; 2448 Label need_conversion;
2509 Label index_out_of_range; 2449 Label index_out_of_range;
(...skipping 18 matching lines...) Expand all
2528 __ bind(&need_conversion); 2468 __ bind(&need_conversion);
2529 // Move the undefined value into the result register, which will 2469 // Move the undefined value into the result register, which will
2530 // trigger conversion. 2470 // trigger conversion.
2531 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 2471 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2532 __ jmp(&done); 2472 __ jmp(&done);
2533 2473
2534 NopRuntimeCallHelper call_helper; 2474 NopRuntimeCallHelper call_helper;
2535 generator.GenerateSlow(masm_, call_helper); 2475 generator.GenerateSlow(masm_, call_helper);
2536 2476
2537 __ bind(&done); 2477 __ bind(&done);
2538 Apply(context_, result); 2478 context()->Plug(result);
2539 } 2479 }
2540 2480
2541 2481
2542 void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 2482 void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
2543 ASSERT(args->length() == 2); 2483 ASSERT(args->length() == 2);
2544 2484
2545 VisitForValue(args->at(0), kStack); 2485 VisitForStackValue(args->at(0));
2546 VisitForValue(args->at(1), kAccumulator); 2486 VisitForAccumulatorValue(args->at(1));
2547 2487
2548 Register object = rbx; 2488 Register object = rbx;
2549 Register index = rax; 2489 Register index = rax;
2550 Register scratch1 = rcx; 2490 Register scratch1 = rcx;
2551 Register scratch2 = rdx; 2491 Register scratch2 = rdx;
2552 Register result = rax; 2492 Register result = rax;
2553 2493
2554 __ pop(object); 2494 __ pop(object);
2555 2495
2556 Label need_conversion; 2496 Label need_conversion;
(...skipping 20 matching lines...) Expand all
2577 __ bind(&need_conversion); 2517 __ bind(&need_conversion);
2578 // Move smi zero into the result register, which will trigger 2518 // Move smi zero into the result register, which will trigger
2579 // conversion. 2519 // conversion.
2580 __ Move(result, Smi::FromInt(0)); 2520 __ Move(result, Smi::FromInt(0));
2581 __ jmp(&done); 2521 __ jmp(&done);
2582 2522
2583 NopRuntimeCallHelper call_helper; 2523 NopRuntimeCallHelper call_helper;
2584 generator.GenerateSlow(masm_, call_helper); 2524 generator.GenerateSlow(masm_, call_helper);
2585 2525
2586 __ bind(&done); 2526 __ bind(&done);
2587 Apply(context_, result); 2527 context()->Plug(result);
2588 } 2528 }
2589 2529
2590 2530
2591 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 2531 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
2592 ASSERT_EQ(2, args->length()); 2532 ASSERT_EQ(2, args->length());
2593 2533
2594 VisitForValue(args->at(0), kStack); 2534 VisitForStackValue(args->at(0));
2595 VisitForValue(args->at(1), kStack); 2535 VisitForStackValue(args->at(1));
2596 2536
2597 StringAddStub stub(NO_STRING_ADD_FLAGS); 2537 StringAddStub stub(NO_STRING_ADD_FLAGS);
2598 __ CallStub(&stub); 2538 __ CallStub(&stub);
2599 Apply(context_, rax); 2539 context()->Plug(rax);
2600 } 2540 }
2601 2541
2602 2542
2603 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 2543 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
2604 ASSERT_EQ(2, args->length()); 2544 ASSERT_EQ(2, args->length());
2605 2545
2606 VisitForValue(args->at(0), kStack); 2546 VisitForStackValue(args->at(0));
2607 VisitForValue(args->at(1), kStack); 2547 VisitForStackValue(args->at(1));
2608 2548
2609 StringCompareStub stub; 2549 StringCompareStub stub;
2610 __ CallStub(&stub); 2550 __ CallStub(&stub);
2611 Apply(context_, rax); 2551 context()->Plug(rax);
2612 } 2552 }
2613 2553
2614 2554
2615 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 2555 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2616 // Load the argument on the stack and call the stub. 2556 // Load the argument on the stack and call the stub.
2617 TranscendentalCacheStub stub(TranscendentalCache::SIN); 2557 TranscendentalCacheStub stub(TranscendentalCache::SIN);
2618 ASSERT(args->length() == 1); 2558 ASSERT(args->length() == 1);
2619 VisitForValue(args->at(0), kStack); 2559 VisitForStackValue(args->at(0));
2620 __ CallStub(&stub); 2560 __ CallStub(&stub);
2621 Apply(context_, rax); 2561 context()->Plug(rax);
2622 } 2562 }
2623 2563
2624 2564
2625 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 2565 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2626 // Load the argument on the stack and call the stub. 2566 // Load the argument on the stack and call the stub.
2627 TranscendentalCacheStub stub(TranscendentalCache::COS); 2567 TranscendentalCacheStub stub(TranscendentalCache::COS);
2628 ASSERT(args->length() == 1); 2568 ASSERT(args->length() == 1);
2629 VisitForValue(args->at(0), kStack); 2569 VisitForStackValue(args->at(0));
2630 __ CallStub(&stub); 2570 __ CallStub(&stub);
2631 Apply(context_, rax); 2571 context()->Plug(rax);
2632 } 2572 }
2633 2573
2634 2574
2635 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 2575 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2636 // Load the argument on the stack and call the runtime function. 2576 // Load the argument on the stack and call the runtime function.
2637 ASSERT(args->length() == 1); 2577 ASSERT(args->length() == 1);
2638 VisitForValue(args->at(0), kStack); 2578 VisitForStackValue(args->at(0));
2639 __ CallRuntime(Runtime::kMath_sqrt, 1); 2579 __ CallRuntime(Runtime::kMath_sqrt, 1);
2640 Apply(context_, rax); 2580 context()->Plug(rax);
2641 } 2581 }
2642 2582
2643 2583
2644 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 2584 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
2645 ASSERT(args->length() >= 2); 2585 ASSERT(args->length() >= 2);
2646 2586
2647 int arg_count = args->length() - 2; // For receiver and function. 2587 int arg_count = args->length() - 2; // For receiver and function.
2648 VisitForValue(args->at(0), kStack); // Receiver. 2588 VisitForStackValue(args->at(0)); // Receiver.
2649 for (int i = 0; i < arg_count; i++) { 2589 for (int i = 0; i < arg_count; i++) {
2650 VisitForValue(args->at(i + 1), kStack); 2590 VisitForStackValue(args->at(i + 1));
2651 } 2591 }
2652 VisitForValue(args->at(arg_count + 1), kAccumulator); // Function. 2592 VisitForAccumulatorValue(args->at(arg_count + 1)); // Function.
2653 2593
2654 // InvokeFunction requires function in rdi. Move it in there. 2594 // InvokeFunction requires function in rdi. Move it in there.
2655 if (!result_register().is(rdi)) __ movq(rdi, result_register()); 2595 if (!result_register().is(rdi)) __ movq(rdi, result_register());
2656 ParameterCount count(arg_count); 2596 ParameterCount count(arg_count);
2657 __ InvokeFunction(rdi, count, CALL_FUNCTION); 2597 __ InvokeFunction(rdi, count, CALL_FUNCTION);
2658 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2598 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2659 Apply(context_, rax); 2599 context()->Plug(rax);
2660 } 2600 }
2661 2601
2662 2602
2663 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 2603 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
2664 ASSERT(args->length() == 3); 2604 ASSERT(args->length() == 3);
2665 VisitForValue(args->at(0), kStack); 2605 VisitForStackValue(args->at(0));
2666 VisitForValue(args->at(1), kStack); 2606 VisitForStackValue(args->at(1));
2667 VisitForValue(args->at(2), kStack); 2607 VisitForStackValue(args->at(2));
2668 __ CallRuntime(Runtime::kRegExpConstructResult, 3); 2608 __ CallRuntime(Runtime::kRegExpConstructResult, 3);
2669 Apply(context_, rax); 2609 context()->Plug(rax);
2670 } 2610 }
2671 2611
2672 2612
2673 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 2613 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
2674 ASSERT(args->length() == 3); 2614 ASSERT(args->length() == 3);
2675 VisitForValue(args->at(0), kStack); 2615 VisitForStackValue(args->at(0));
2676 VisitForValue(args->at(1), kStack); 2616 VisitForStackValue(args->at(1));
2677 VisitForValue(args->at(2), kStack); 2617 VisitForStackValue(args->at(2));
2678 __ CallRuntime(Runtime::kSwapElements, 3); 2618 __ CallRuntime(Runtime::kSwapElements, 3);
2679 Apply(context_, rax); 2619 context()->Plug(rax);
2680 } 2620 }
2681 2621
2682 2622
2683 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 2623 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
2684 ASSERT_EQ(2, args->length()); 2624 ASSERT_EQ(2, args->length());
2685 2625
2686 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 2626 ASSERT_NE(NULL, args->at(0)->AsLiteral());
2687 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 2627 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
2688 2628
2689 Handle<FixedArray> jsfunction_result_caches( 2629 Handle<FixedArray> jsfunction_result_caches(
2690 Top::global_context()->jsfunction_result_caches()); 2630 Top::global_context()->jsfunction_result_caches());
2691 if (jsfunction_result_caches->length() <= cache_id) { 2631 if (jsfunction_result_caches->length() <= cache_id) {
2692 __ Abort("Attempt to use undefined cache."); 2632 __ Abort("Attempt to use undefined cache.");
2693 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2633 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2694 Apply(context_, rax); 2634 context()->Plug(rax);
2695 return; 2635 return;
2696 } 2636 }
2697 2637
2698 VisitForValue(args->at(1), kAccumulator); 2638 VisitForAccumulatorValue(args->at(1));
2699 2639
2700 Register key = rax; 2640 Register key = rax;
2701 Register cache = rbx; 2641 Register cache = rbx;
2702 Register tmp = rcx; 2642 Register tmp = rcx;
2703 __ movq(cache, ContextOperand(rsi, Context::GLOBAL_INDEX)); 2643 __ movq(cache, ContextOperand(rsi, Context::GLOBAL_INDEX));
2704 __ movq(cache, 2644 __ movq(cache,
2705 FieldOperand(cache, GlobalObject::kGlobalContextOffset)); 2645 FieldOperand(cache, GlobalObject::kGlobalContextOffset));
2706 __ movq(cache, 2646 __ movq(cache,
2707 ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 2647 ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2708 __ movq(cache, 2648 __ movq(cache,
(...skipping 16 matching lines...) Expand all
2725 FixedArray::kHeaderSize + kPointerSize)); 2665 FixedArray::kHeaderSize + kPointerSize));
2726 __ jmp(&done); 2666 __ jmp(&done);
2727 2667
2728 __ bind(&not_found); 2668 __ bind(&not_found);
2729 // Call runtime to perform the lookup. 2669 // Call runtime to perform the lookup.
2730 __ push(cache); 2670 __ push(cache);
2731 __ push(key); 2671 __ push(key);
2732 __ CallRuntime(Runtime::kGetFromCache, 2); 2672 __ CallRuntime(Runtime::kGetFromCache, 2);
2733 2673
2734 __ bind(&done); 2674 __ bind(&done);
2735 Apply(context_, rax); 2675 context()->Plug(rax);
2736 } 2676 }
2737 2677
2738 2678
2739 void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { 2679 void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
2740 ASSERT_EQ(2, args->length()); 2680 ASSERT_EQ(2, args->length());
2741 2681
2742 Register right = rax; 2682 Register right = rax;
2743 Register left = rbx; 2683 Register left = rbx;
2744 Register tmp = rcx; 2684 Register tmp = rcx;
2745 2685
2746 VisitForValue(args->at(0), kStack); 2686 VisitForStackValue(args->at(0));
2747 VisitForValue(args->at(1), kAccumulator); 2687 VisitForAccumulatorValue(args->at(1));
2748 __ pop(left); 2688 __ pop(left);
2749 2689
2750 Label done, fail, ok; 2690 Label done, fail, ok;
2751 __ cmpq(left, right); 2691 __ cmpq(left, right);
2752 __ j(equal, &ok); 2692 __ j(equal, &ok);
2753 // Fail if either is a non-HeapObject. 2693 // Fail if either is a non-HeapObject.
2754 Condition either_smi = masm()->CheckEitherSmi(left, right, tmp); 2694 Condition either_smi = masm()->CheckEitherSmi(left, right, tmp);
2755 __ j(either_smi, &fail); 2695 __ j(either_smi, &fail);
2756 __ j(zero, &fail); 2696 __ j(zero, &fail);
2757 __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset)); 2697 __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset));
2758 __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset), 2698 __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset),
2759 Immediate(JS_REGEXP_TYPE)); 2699 Immediate(JS_REGEXP_TYPE));
2760 __ j(not_equal, &fail); 2700 __ j(not_equal, &fail);
2761 __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset)); 2701 __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset));
2762 __ j(not_equal, &fail); 2702 __ j(not_equal, &fail);
2763 __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset)); 2703 __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset));
2764 __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset)); 2704 __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset));
2765 __ j(equal, &ok); 2705 __ j(equal, &ok);
2766 __ bind(&fail); 2706 __ bind(&fail);
2767 __ Move(rax, Factory::false_value()); 2707 __ Move(rax, Factory::false_value());
2768 __ jmp(&done); 2708 __ jmp(&done);
2769 __ bind(&ok); 2709 __ bind(&ok);
2770 __ Move(rax, Factory::true_value()); 2710 __ Move(rax, Factory::true_value());
2771 __ bind(&done); 2711 __ bind(&done);
2772 2712
2773 Apply(context_, rax); 2713 context()->Plug(rax);
2774 } 2714 }
2775 2715
2776 2716
2777 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { 2717 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
2778 ASSERT(args->length() == 1); 2718 ASSERT(args->length() == 1);
2779 2719
2780 VisitForValue(args->at(0), kAccumulator); 2720 VisitForAccumulatorValue(args->at(0));
2781 2721
2782 Label materialize_true, materialize_false; 2722 Label materialize_true, materialize_false;
2783 Label* if_true = NULL; 2723 Label* if_true = NULL;
2784 Label* if_false = NULL; 2724 Label* if_false = NULL;
2785 Label* fall_through = NULL; 2725 Label* fall_through = NULL;
2786 PrepareTest(&materialize_true, &materialize_false, 2726 context()->PrepareTest(&materialize_true, &materialize_false,
2787 &if_true, &if_false, &fall_through); 2727 &if_true, &if_false, &fall_through);
2788 2728
2789 __ testl(FieldOperand(rax, String::kHashFieldOffset), 2729 __ testl(FieldOperand(rax, String::kHashFieldOffset),
2790 Immediate(String::kContainsCachedArrayIndexMask)); 2730 Immediate(String::kContainsCachedArrayIndexMask));
2791 __ j(zero, if_true); 2731 __ j(zero, if_true);
2792 __ jmp(if_false); 2732 __ jmp(if_false);
2793 2733
2794 Apply(context_, if_true, if_false); 2734 context()->Plug(if_true, if_false);
2795 } 2735 }
2796 2736
2797 2737
2798 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 2738 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
2799 ASSERT(args->length() == 1); 2739 ASSERT(args->length() == 1);
2800 2740
2801 VisitForValue(args->at(0), kAccumulator); 2741 VisitForAccumulatorValue(args->at(0));
2802 2742
2803 __ movl(rax, FieldOperand(rax, String::kHashFieldOffset)); 2743 __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
2804 ASSERT(String::kHashShift >= kSmiTagSize); 2744 ASSERT(String::kHashShift >= kSmiTagSize);
2805 __ IndexFromHash(rax, rax); 2745 __ IndexFromHash(rax, rax);
2806 2746
2807 Apply(context_, rax); 2747 context()->Plug(rax);
2808 } 2748 }
2809 2749
2810 2750
2811 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2751 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2812 Handle<String> name = expr->name(); 2752 Handle<String> name = expr->name();
2813 if (name->length() > 0 && name->Get(0) == '_') { 2753 if (name->length() > 0 && name->Get(0) == '_') {
2814 Comment cmnt(masm_, "[ InlineRuntimeCall"); 2754 Comment cmnt(masm_, "[ InlineRuntimeCall");
2815 EmitInlineRuntimeCall(expr); 2755 EmitInlineRuntimeCall(expr);
2816 return; 2756 return;
2817 } 2757 }
2818 2758
2819 Comment cmnt(masm_, "[ CallRuntime"); 2759 Comment cmnt(masm_, "[ CallRuntime");
2820 ZoneList<Expression*>* args = expr->arguments(); 2760 ZoneList<Expression*>* args = expr->arguments();
2821 2761
2822 if (expr->is_jsruntime()) { 2762 if (expr->is_jsruntime()) {
2823 // Prepare for calling JS runtime function. 2763 // Prepare for calling JS runtime function.
2824 __ movq(rax, CodeGenerator::GlobalObject()); 2764 __ movq(rax, CodeGenerator::GlobalObject());
2825 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 2765 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
2826 } 2766 }
2827 2767
2828 // Push the arguments ("left-to-right"). 2768 // Push the arguments ("left-to-right").
2829 int arg_count = args->length(); 2769 int arg_count = args->length();
2830 for (int i = 0; i < arg_count; i++) { 2770 for (int i = 0; i < arg_count; i++) {
2831 VisitForValue(args->at(i), kStack); 2771 VisitForStackValue(args->at(i));
2832 } 2772 }
2833 2773
2834 if (expr->is_jsruntime()) { 2774 if (expr->is_jsruntime()) {
2835 // Call the JS runtime function using a call IC. 2775 // Call the JS runtime function using a call IC.
2836 __ Move(rcx, expr->name()); 2776 __ Move(rcx, expr->name());
2837 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2777 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2838 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 2778 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
2839 __ call(ic, RelocInfo::CODE_TARGET); 2779 __ call(ic, RelocInfo::CODE_TARGET);
2840 // Restore context register. 2780 // Restore context register.
2841 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2781 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2842 } else { 2782 } else {
2843 __ CallRuntime(expr->function(), arg_count); 2783 __ CallRuntime(expr->function(), arg_count);
2844 } 2784 }
2845 Apply(context_, rax); 2785 context()->Plug(rax);
2846 } 2786 }
2847 2787
2848 2788
2849 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2789 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2850 switch (expr->op()) { 2790 switch (expr->op()) {
2851 case Token::DELETE: { 2791 case Token::DELETE: {
2852 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 2792 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2853 Property* prop = expr->expression()->AsProperty(); 2793 Property* prop = expr->expression()->AsProperty();
2854 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 2794 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
2855 if (prop == NULL && var == NULL) { 2795 if (prop == NULL && var == NULL) {
2856 // Result of deleting non-property, non-variable reference is true. 2796 // Result of deleting non-property, non-variable reference is true.
2857 // The subexpression may have side effects. 2797 // The subexpression may have side effects.
2858 VisitForEffect(expr->expression()); 2798 VisitForEffect(expr->expression());
2859 Apply(context_, true); 2799 context()->Plug(true);
2860 } else if (var != NULL && 2800 } else if (var != NULL &&
2861 !var->is_global() && 2801 !var->is_global() &&
2862 var->slot() != NULL && 2802 var->slot() != NULL &&
2863 var->slot()->type() != Slot::LOOKUP) { 2803 var->slot()->type() != Slot::LOOKUP) {
2864 // Result of deleting non-global, non-dynamic variables is false. 2804 // Result of deleting non-global, non-dynamic variables is false.
2865 // The subexpression does not have side effects. 2805 // The subexpression does not have side effects.
2866 Apply(context_, false); 2806 context()->Plug(false);
2867 } else { 2807 } else {
2868 // Property or variable reference. Call the delete builtin with 2808 // Property or variable reference. Call the delete builtin with
2869 // object and property name as arguments. 2809 // object and property name as arguments.
2870 if (prop != NULL) { 2810 if (prop != NULL) {
2871 VisitForValue(prop->obj(), kStack); 2811 VisitForStackValue(prop->obj());
2872 VisitForValue(prop->key(), kStack); 2812 VisitForStackValue(prop->key());
2873 } else if (var->is_global()) { 2813 } else if (var->is_global()) {
2874 __ push(CodeGenerator::GlobalObject()); 2814 __ push(CodeGenerator::GlobalObject());
2875 __ Push(var->name()); 2815 __ Push(var->name());
2876 } else { 2816 } else {
2877 // Non-global variable. Call the runtime to look up the context 2817 // Non-global variable. Call the runtime to look up the context
2878 // where the variable was introduced. 2818 // where the variable was introduced.
2879 __ push(context_register()); 2819 __ push(context_register());
2880 __ Push(var->name()); 2820 __ Push(var->name());
2881 __ CallRuntime(Runtime::kLookupContext, 2); 2821 __ CallRuntime(Runtime::kLookupContext, 2);
2882 __ push(rax); 2822 __ push(rax);
2883 __ Push(var->name()); 2823 __ Push(var->name());
2884 } 2824 }
2885 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 2825 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
2886 Apply(context_, rax); 2826 context()->Plug(rax);
2887 } 2827 }
2888 break; 2828 break;
2889 } 2829 }
2890 2830
2891 case Token::VOID: { 2831 case Token::VOID: {
2892 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 2832 Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2893 VisitForEffect(expr->expression()); 2833 VisitForEffect(expr->expression());
2894 switch (context_) { 2834 context()->Plug(Heap::kUndefinedValueRootIndex);
2895 case Expression::kUninitialized:
2896 UNREACHABLE();
2897 break;
2898 case Expression::kEffect:
2899 break;
2900 case Expression::kValue:
2901 switch (location_) {
2902 case kAccumulator:
2903 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
2904 break;
2905 case kStack:
2906 __ PushRoot(Heap::kUndefinedValueRootIndex);
2907 break;
2908 }
2909 break;
2910 case Expression::kTest:
2911 __ jmp(false_label_);
2912 break;
2913 }
2914 break; 2835 break;
2915 } 2836 }
2916 2837
2917 case Token::NOT: { 2838 case Token::NOT: {
2918 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2839 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2919 Label materialize_true, materialize_false; 2840 Label materialize_true, materialize_false;
2920 Label* if_true = NULL; 2841 Label* if_true = NULL;
2921 Label* if_false = NULL; 2842 Label* if_false = NULL;
2922 Label* fall_through = NULL; 2843 Label* fall_through = NULL;
2923 // Notice that the labels are swapped. 2844 // Notice that the labels are swapped.
2924 PrepareTest(&materialize_true, &materialize_false, 2845 context()->PrepareTest(&materialize_true, &materialize_false,
2925 &if_false, &if_true, &fall_through); 2846 &if_false, &if_true, &fall_through);
2926 VisitForControl(expr->expression(), if_true, if_false, fall_through); 2847 VisitForControl(expr->expression(), if_true, if_false, fall_through);
2927 Apply(context_, if_false, if_true); // Labels swapped. 2848 context()->Plug(if_false, if_true); // Labels swapped.
2928 break; 2849 break;
2929 } 2850 }
2930 2851
2931 case Token::TYPEOF: { 2852 case Token::TYPEOF: {
2932 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 2853 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2933 VisitForTypeofValue(expr->expression(), kStack); 2854 { StackValueContext context(this);
2855 VisitForTypeofValue(expr->expression());
2856 }
2934 __ CallRuntime(Runtime::kTypeof, 1); 2857 __ CallRuntime(Runtime::kTypeof, 1);
2935 Apply(context_, rax); 2858 context()->Plug(rax);
2936 break; 2859 break;
2937 } 2860 }
2938 2861
2939 case Token::ADD: { 2862 case Token::ADD: {
2940 Comment cmt(masm_, "[ UnaryOperation (ADD)"); 2863 Comment cmt(masm_, "[ UnaryOperation (ADD)");
2941 VisitForValue(expr->expression(), kAccumulator); 2864 VisitForAccumulatorValue(expr->expression());
2942 Label no_conversion; 2865 Label no_conversion;
2943 Condition is_smi = masm_->CheckSmi(result_register()); 2866 Condition is_smi = masm_->CheckSmi(result_register());
2944 __ j(is_smi, &no_conversion); 2867 __ j(is_smi, &no_conversion);
2945 __ push(result_register()); 2868 __ push(result_register());
2946 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 2869 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
2947 __ bind(&no_conversion); 2870 __ bind(&no_conversion);
2948 Apply(context_, result_register()); 2871 context()->Plug(result_register());
2949 break; 2872 break;
2950 } 2873 }
2951 2874
2952 case Token::SUB: { 2875 case Token::SUB: {
2953 Comment cmt(masm_, "[ UnaryOperation (SUB)"); 2876 Comment cmt(masm_, "[ UnaryOperation (SUB)");
2954 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); 2877 bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
2955 UnaryOverwriteMode overwrite = 2878 UnaryOverwriteMode overwrite =
2956 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 2879 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
2957 GenericUnaryOpStub stub(Token::SUB, overwrite); 2880 GenericUnaryOpStub stub(Token::SUB, overwrite);
2958 // GenericUnaryOpStub expects the argument to be in the 2881 // GenericUnaryOpStub expects the argument to be in the
2959 // accumulator register rax. 2882 // accumulator register rax.
2960 VisitForValue(expr->expression(), kAccumulator); 2883 VisitForAccumulatorValue(expr->expression());
2961 __ CallStub(&stub); 2884 __ CallStub(&stub);
2962 Apply(context_, rax); 2885 context()->Plug(rax);
2963 break; 2886 break;
2964 } 2887 }
2965 2888
2966 case Token::BIT_NOT: { 2889 case Token::BIT_NOT: {
2967 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); 2890 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
2968 // The generic unary operation stub expects the argument to be 2891 // The generic unary operation stub expects the argument to be
2969 // in the accumulator register rax. 2892 // in the accumulator register rax.
2970 VisitForValue(expr->expression(), kAccumulator); 2893 VisitForAccumulatorValue(expr->expression());
2971 Label done; 2894 Label done;
2972 if (ShouldInlineSmiCase(expr->op())) { 2895 if (ShouldInlineSmiCase(expr->op())) {
2973 Label call_stub; 2896 Label call_stub;
2974 __ JumpIfNotSmi(rax, &call_stub); 2897 __ JumpIfNotSmi(rax, &call_stub);
2975 __ SmiNot(rax, rax); 2898 __ SmiNot(rax, rax);
2976 __ jmp(&done); 2899 __ jmp(&done);
2977 __ bind(&call_stub); 2900 __ bind(&call_stub);
2978 } 2901 }
2979 bool overwrite = expr->expression()->ResultOverwriteAllowed(); 2902 bool overwrite = expr->expression()->ResultOverwriteAllowed();
2980 UnaryOverwriteMode mode = 2903 UnaryOverwriteMode mode =
2981 overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 2904 overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
2982 GenericUnaryOpStub stub(Token::BIT_NOT, mode); 2905 GenericUnaryOpStub stub(Token::BIT_NOT, mode);
2983 __ CallStub(&stub); 2906 __ CallStub(&stub);
2984 __ bind(&done); 2907 __ bind(&done);
2985 Apply(context_, rax); 2908 context()->Plug(rax);
2986 break; 2909 break;
2987 } 2910 }
2988 2911
2989 default: 2912 default:
2990 UNREACHABLE(); 2913 UNREACHABLE();
2991 } 2914 }
2992 } 2915 }
2993 2916
2994 2917
2995 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 2918 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
(...skipping 15 matching lines...) Expand all
3011 // In case of a property we use the uninitialized expression context 2934 // In case of a property we use the uninitialized expression context
3012 // of the key to detect a named property. 2935 // of the key to detect a named property.
3013 if (prop != NULL) { 2936 if (prop != NULL) {
3014 assign_type = 2937 assign_type =
3015 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 2938 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3016 } 2939 }
3017 2940
3018 // Evaluate expression and get value. 2941 // Evaluate expression and get value.
3019 if (assign_type == VARIABLE) { 2942 if (assign_type == VARIABLE) {
3020 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 2943 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
3021 Location saved_location = location_; 2944 AccumulatorValueContext context(this);
3022 location_ = kAccumulator; 2945 EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
3023 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
3024 Expression::kValue);
3025 location_ = saved_location;
3026 } else { 2946 } else {
3027 // Reserve space for result of postfix operation. 2947 // Reserve space for result of postfix operation.
3028 if (expr->is_postfix() && context_ != Expression::kEffect) { 2948 if (expr->is_postfix() && !context()->IsEffect()) {
3029 __ Push(Smi::FromInt(0)); 2949 __ Push(Smi::FromInt(0));
3030 } 2950 }
3031 if (assign_type == NAMED_PROPERTY) { 2951 if (assign_type == NAMED_PROPERTY) {
3032 VisitForValue(prop->obj(), kAccumulator); 2952 VisitForAccumulatorValue(prop->obj());
3033 __ push(rax); // Copy of receiver, needed for later store. 2953 __ push(rax); // Copy of receiver, needed for later store.
3034 EmitNamedPropertyLoad(prop); 2954 EmitNamedPropertyLoad(prop);
3035 } else { 2955 } else {
3036 VisitForValue(prop->obj(), kStack); 2956 VisitForStackValue(prop->obj());
3037 VisitForValue(prop->key(), kAccumulator); 2957 VisitForAccumulatorValue(prop->key());
3038 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 2958 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack
3039 __ push(rax); // Copy of key, needed for later store. 2959 __ push(rax); // Copy of key, needed for later store.
3040 EmitKeyedPropertyLoad(prop); 2960 EmitKeyedPropertyLoad(prop);
3041 } 2961 }
3042 } 2962 }
3043 2963
3044 // Call ToNumber only if operand is not a smi. 2964 // Call ToNumber only if operand is not a smi.
3045 Label no_conversion; 2965 Label no_conversion;
3046 Condition is_smi; 2966 Condition is_smi;
3047 is_smi = masm_->CheckSmi(rax); 2967 is_smi = masm_->CheckSmi(rax);
3048 __ j(is_smi, &no_conversion); 2968 __ j(is_smi, &no_conversion);
3049 __ push(rax); 2969 __ push(rax);
3050 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 2970 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
3051 __ bind(&no_conversion); 2971 __ bind(&no_conversion);
3052 2972
3053 // Save result for postfix expressions. 2973 // Save result for postfix expressions.
3054 if (expr->is_postfix()) { 2974 if (expr->is_postfix()) {
3055 switch (context_) { 2975 if (!context()->IsEffect()) {
3056 case Expression::kUninitialized: 2976 // Save the result on the stack. If we have a named or keyed property
3057 UNREACHABLE(); 2977 // we store the result under the receiver that is currently on top
3058 case Expression::kEffect: 2978 // of the stack.
3059 // Do not save result. 2979 switch (assign_type) {
3060 break; 2980 case VARIABLE:
3061 case Expression::kValue: 2981 __ push(rax);
3062 case Expression::kTest: 2982 break;
3063 // Save the result on the stack. If we have a named or keyed property 2983 case NAMED_PROPERTY:
3064 // we store the result under the receiver that is currently on top 2984 __ movq(Operand(rsp, kPointerSize), rax);
3065 // of the stack. 2985 break;
3066 switch (assign_type) { 2986 case KEYED_PROPERTY:
3067 case VARIABLE: 2987 __ movq(Operand(rsp, 2 * kPointerSize), rax);
3068 __ push(rax); 2988 break;
3069 break; 2989 }
3070 case NAMED_PROPERTY:
3071 __ movq(Operand(rsp, kPointerSize), rax);
3072 break;
3073 case KEYED_PROPERTY:
3074 __ movq(Operand(rsp, 2 * kPointerSize), rax);
3075 break;
3076 }
3077 break;
3078 } 2990 }
3079 } 2991 }
3080 2992
3081 // Inline smi case if we are in a loop. 2993 // Inline smi case if we are in a loop.
3082 Label stub_call, done; 2994 Label stub_call, done;
3083 if (ShouldInlineSmiCase(expr->op())) { 2995 if (ShouldInlineSmiCase(expr->op())) {
3084 if (expr->op() == Token::INC) { 2996 if (expr->op() == Token::INC) {
3085 __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 2997 __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3086 } else { 2998 } else {
3087 __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 2999 __ SmiSubConstant(rax, rax, Smi::FromInt(1));
(...skipping 16 matching lines...) Expand all
3104 NO_OVERWRITE, 3016 NO_OVERWRITE,
3105 NO_GENERIC_BINARY_FLAGS); 3017 NO_GENERIC_BINARY_FLAGS);
3106 stub.GenerateCall(masm_, rax, Smi::FromInt(1)); 3018 stub.GenerateCall(masm_, rax, Smi::FromInt(1));
3107 __ bind(&done); 3019 __ bind(&done);
3108 3020
3109 // Store the value returned in rax. 3021 // Store the value returned in rax.
3110 switch (assign_type) { 3022 switch (assign_type) {
3111 case VARIABLE: 3023 case VARIABLE:
3112 if (expr->is_postfix()) { 3024 if (expr->is_postfix()) {
3113 // Perform the assignment as if via '='. 3025 // Perform the assignment as if via '='.
3114 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3026 { EffectContext context(this);
3115 Token::ASSIGN, 3027 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3116 Expression::kEffect); 3028 Token::ASSIGN);
3029 }
3117 // For all contexts except kEffect: We have the result on 3030 // For all contexts except kEffect: We have the result on
3118 // top of the stack. 3031 // top of the stack.
3119 if (context_ != Expression::kEffect) { 3032 if (!context()->IsEffect()) {
3120 ApplyTOS(context_); 3033 context()->PlugTOS();
3121 } 3034 }
3122 } else { 3035 } else {
3123 // Perform the assignment as if via '='. 3036 // Perform the assignment as if via '='.
3124 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3037 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3125 Token::ASSIGN, 3038 Token::ASSIGN);
3126 context_);
3127 } 3039 }
3128 break; 3040 break;
3129 case NAMED_PROPERTY: { 3041 case NAMED_PROPERTY: {
3130 __ Move(rcx, prop->key()->AsLiteral()->handle()); 3042 __ Move(rcx, prop->key()->AsLiteral()->handle());
3131 __ pop(rdx); 3043 __ pop(rdx);
3132 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3044 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3133 __ call(ic, RelocInfo::CODE_TARGET); 3045 __ call(ic, RelocInfo::CODE_TARGET);
3134 // This nop signals to the IC that there is no inlined code at the call 3046 // This nop signals to the IC that there is no inlined code at the call
3135 // site for it to patch. 3047 // site for it to patch.
3136 __ nop(); 3048 __ nop();
3137 if (expr->is_postfix()) { 3049 if (expr->is_postfix()) {
3138 if (context_ != Expression::kEffect) { 3050 if (!context()->IsEffect()) {
3139 ApplyTOS(context_); 3051 context()->PlugTOS();
3140 } 3052 }
3141 } else { 3053 } else {
3142 Apply(context_, rax); 3054 context()->Plug(rax);
3143 } 3055 }
3144 break; 3056 break;
3145 } 3057 }
3146 case KEYED_PROPERTY: { 3058 case KEYED_PROPERTY: {
3147 __ pop(rcx); 3059 __ pop(rcx);
3148 __ pop(rdx); 3060 __ pop(rdx);
3149 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 3061 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
3150 __ call(ic, RelocInfo::CODE_TARGET); 3062 __ call(ic, RelocInfo::CODE_TARGET);
3151 // This nop signals to the IC that there is no inlined code at the call 3063 // This nop signals to the IC that there is no inlined code at the call
3152 // site for it to patch. 3064 // site for it to patch.
3153 __ nop(); 3065 __ nop();
3154 if (expr->is_postfix()) { 3066 if (expr->is_postfix()) {
3155 if (context_ != Expression::kEffect) { 3067 if (!context()->IsEffect()) {
3156 ApplyTOS(context_); 3068 context()->PlugTOS();
3157 } 3069 }
3158 } else { 3070 } else {
3159 Apply(context_, rax); 3071 context()->Plug(rax);
3160 } 3072 }
3161 break; 3073 break;
3162 } 3074 }
3163 } 3075 }
3164 } 3076 }
3165 3077
3166 3078
3167 void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { 3079 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
3168 VariableProxy* proxy = expr->AsVariableProxy(); 3080 VariableProxy* proxy = expr->AsVariableProxy();
3081 ASSERT(!context()->IsEffect());
3082 ASSERT(!context()->IsTest());
3083
3169 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { 3084 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
3170 Comment cmnt(masm_, "Global variable"); 3085 Comment cmnt(masm_, "Global variable");
3171 __ Move(rcx, proxy->name()); 3086 __ Move(rcx, proxy->name());
3172 __ movq(rax, CodeGenerator::GlobalObject()); 3087 __ movq(rax, CodeGenerator::GlobalObject());
3173 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3088 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3174 // Use a regular load, not a contextual load, to avoid a reference 3089 // Use a regular load, not a contextual load, to avoid a reference
3175 // error. 3090 // error.
3176 __ Call(ic, RelocInfo::CODE_TARGET); 3091 __ Call(ic, RelocInfo::CODE_TARGET);
3177 if (where == kStack) __ push(rax); 3092 context()->Plug(rax);
3178 } else if (proxy != NULL && 3093 } else if (proxy != NULL &&
3179 proxy->var()->slot() != NULL && 3094 proxy->var()->slot() != NULL &&
3180 proxy->var()->slot()->type() == Slot::LOOKUP) { 3095 proxy->var()->slot()->type() == Slot::LOOKUP) {
3181 Label done, slow; 3096 Label done, slow;
3182 3097
3183 // Generate code for loading from variables potentially shadowed 3098 // Generate code for loading from variables potentially shadowed
3184 // by eval-introduced variables. 3099 // by eval-introduced variables.
3185 Slot* slot = proxy->var()->slot(); 3100 Slot* slot = proxy->var()->slot();
3186 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); 3101 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
3187 3102
3188 __ bind(&slow); 3103 __ bind(&slow);
3189 __ push(rsi); 3104 __ push(rsi);
3190 __ Push(proxy->name()); 3105 __ Push(proxy->name());
3191 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3106 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3192 __ bind(&done); 3107 __ bind(&done);
3193 3108
3194 if (where == kStack) __ push(rax); 3109 context()->Plug(rax);
3195 } else { 3110 } else {
3196 // This expression cannot throw a reference error at the top level. 3111 // This expression cannot throw a reference error at the top level.
3197 VisitForValue(expr, where); 3112 Visit(expr);
3198 } 3113 }
3199 } 3114 }
3200 3115
3201 3116
3202 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, 3117 bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
3203 Expression* left, 3118 Expression* left,
3204 Expression* right, 3119 Expression* right,
3205 Label* if_true, 3120 Label* if_true,
3206 Label* if_false, 3121 Label* if_false,
3207 Label* fall_through) { 3122 Label* fall_through) {
3208 if (op != Token::EQ && op != Token::EQ_STRICT) return false; 3123 if (op != Token::EQ && op != Token::EQ_STRICT) return false;
3209 3124
3210 // Check for the pattern: typeof <expression> == <string literal>. 3125 // Check for the pattern: typeof <expression> == <string literal>.
3211 Literal* right_literal = right->AsLiteral(); 3126 Literal* right_literal = right->AsLiteral();
3212 if (right_literal == NULL) return false; 3127 if (right_literal == NULL) return false;
3213 Handle<Object> right_literal_value = right_literal->handle(); 3128 Handle<Object> right_literal_value = right_literal->handle();
3214 if (!right_literal_value->IsString()) return false; 3129 if (!right_literal_value->IsString()) return false;
3215 UnaryOperation* left_unary = left->AsUnaryOperation(); 3130 UnaryOperation* left_unary = left->AsUnaryOperation();
3216 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; 3131 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
3217 Handle<String> check = Handle<String>::cast(right_literal_value); 3132 Handle<String> check = Handle<String>::cast(right_literal_value);
3218 3133
3219 VisitForTypeofValue(left_unary->expression(), kAccumulator); 3134 { AccumulatorValueContext context(this);
3135 VisitForTypeofValue(left_unary->expression());
3136 }
3137
3220 if (check->Equals(Heap::number_symbol())) { 3138 if (check->Equals(Heap::number_symbol())) {
3221 Condition is_smi = masm_->CheckSmi(rax); 3139 Condition is_smi = masm_->CheckSmi(rax);
3222 __ j(is_smi, if_true); 3140 __ j(is_smi, if_true);
3223 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 3141 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
3224 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 3142 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
3225 Split(equal, if_true, if_false, fall_through); 3143 Split(equal, if_true, if_false, fall_through);
3226 } else if (check->Equals(Heap::string_symbol())) { 3144 } else if (check->Equals(Heap::string_symbol())) {
3227 Condition is_smi = masm_->CheckSmi(rax); 3145 Condition is_smi = masm_->CheckSmi(rax);
3228 __ j(is_smi, if_false); 3146 __ j(is_smi, if_false);
3229 // Check for undetectable objects => false. 3147 // Check for undetectable objects => false.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
3284 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 3202 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3285 Comment cmnt(masm_, "[ CompareOperation"); 3203 Comment cmnt(masm_, "[ CompareOperation");
3286 SetSourcePosition(expr->position()); 3204 SetSourcePosition(expr->position());
3287 3205
3288 // Always perform the comparison for its control flow. Pack the result 3206 // Always perform the comparison for its control flow. Pack the result
3289 // into the expression's context after the comparison is performed. 3207 // into the expression's context after the comparison is performed.
3290 Label materialize_true, materialize_false; 3208 Label materialize_true, materialize_false;
3291 Label* if_true = NULL; 3209 Label* if_true = NULL;
3292 Label* if_false = NULL; 3210 Label* if_false = NULL;
3293 Label* fall_through = NULL; 3211 Label* fall_through = NULL;
3294 PrepareTest(&materialize_true, &materialize_false, 3212 context()->PrepareTest(&materialize_true, &materialize_false,
3295 &if_true, &if_false, &fall_through); 3213 &if_true, &if_false, &fall_through);
3296 3214
3297 // First we try a fast inlined version of the compare when one of 3215 // First we try a fast inlined version of the compare when one of
3298 // the operands is a literal. 3216 // the operands is a literal.
3299 Token::Value op = expr->op(); 3217 Token::Value op = expr->op();
3300 Expression* left = expr->left(); 3218 Expression* left = expr->left();
3301 Expression* right = expr->right(); 3219 Expression* right = expr->right();
3302 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { 3220 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
3303 Apply(context_, if_true, if_false); 3221 context()->Plug(if_true, if_false);
3304 return; 3222 return;
3305 } 3223 }
3306 3224
3307 VisitForValue(expr->left(), kStack); 3225 VisitForStackValue(expr->left());
3308 switch (op) { 3226 switch (op) {
3309 case Token::IN: 3227 case Token::IN:
3310 VisitForValue(expr->right(), kStack); 3228 VisitForStackValue(expr->right());
3311 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3229 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3312 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 3230 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
3313 Split(equal, if_true, if_false, fall_through); 3231 Split(equal, if_true, if_false, fall_through);
3314 break; 3232 break;
3315 3233
3316 case Token::INSTANCEOF: { 3234 case Token::INSTANCEOF: {
3317 VisitForValue(expr->right(), kStack); 3235 VisitForStackValue(expr->right());
3318 InstanceofStub stub; 3236 InstanceofStub stub;
3319 __ CallStub(&stub); 3237 __ CallStub(&stub);
3320 __ testq(rax, rax); 3238 __ testq(rax, rax);
3321 // The stub returns 0 for true. 3239 // The stub returns 0 for true.
3322 Split(zero, if_true, if_false, fall_through); 3240 Split(zero, if_true, if_false, fall_through);
3323 break; 3241 break;
3324 } 3242 }
3325 3243
3326 default: { 3244 default: {
3327 VisitForValue(expr->right(), kAccumulator); 3245 VisitForAccumulatorValue(expr->right());
3328 Condition cc = no_condition; 3246 Condition cc = no_condition;
3329 bool strict = false; 3247 bool strict = false;
3330 switch (op) { 3248 switch (op) {
3331 case Token::EQ_STRICT: 3249 case Token::EQ_STRICT:
3332 strict = true; 3250 strict = true;
3333 // Fall through. 3251 // Fall through.
3334 case Token::EQ: 3252 case Token::EQ:
3335 cc = equal; 3253 cc = equal;
3336 __ pop(rdx); 3254 __ pop(rdx);
3337 break; 3255 break;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3371 3289
3372 CompareStub stub(cc, strict); 3290 CompareStub stub(cc, strict);
3373 __ CallStub(&stub); 3291 __ CallStub(&stub);
3374 __ testq(rax, rax); 3292 __ testq(rax, rax);
3375 Split(cc, if_true, if_false, fall_through); 3293 Split(cc, if_true, if_false, fall_through);
3376 } 3294 }
3377 } 3295 }
3378 3296
3379 // Convert the result of the comparison into one expected for this 3297 // Convert the result of the comparison into one expected for this
3380 // expression's context. 3298 // expression's context.
3381 Apply(context_, if_true, if_false); 3299 context()->Plug(if_true, if_false);
3382 } 3300 }
3383 3301
3384 3302
3385 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { 3303 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
3386 Comment cmnt(masm_, "[ CompareToNull"); 3304 Comment cmnt(masm_, "[ CompareToNull");
3387 Label materialize_true, materialize_false; 3305 Label materialize_true, materialize_false;
3388 Label* if_true = NULL; 3306 Label* if_true = NULL;
3389 Label* if_false = NULL; 3307 Label* if_false = NULL;
3390 Label* fall_through = NULL; 3308 Label* fall_through = NULL;
3391 PrepareTest(&materialize_true, &materialize_false, 3309 context()->PrepareTest(&materialize_true, &materialize_false,
3392 &if_true, &if_false, &fall_through); 3310 &if_true, &if_false, &fall_through);
3393 3311
3394 VisitForValue(expr->expression(), kAccumulator); 3312 VisitForAccumulatorValue(expr->expression());
3395 __ CompareRoot(rax, Heap::kNullValueRootIndex); 3313 __ CompareRoot(rax, Heap::kNullValueRootIndex);
3396 if (expr->is_strict()) { 3314 if (expr->is_strict()) {
3397 Split(equal, if_true, if_false, fall_through); 3315 Split(equal, if_true, if_false, fall_through);
3398 } else { 3316 } else {
3399 __ j(equal, if_true); 3317 __ j(equal, if_true);
3400 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 3318 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
3401 __ j(equal, if_true); 3319 __ j(equal, if_true);
3402 Condition is_smi = masm_->CheckSmi(rax); 3320 Condition is_smi = masm_->CheckSmi(rax);
3403 __ j(is_smi, if_false); 3321 __ j(is_smi, if_false);
3404 // It can be an undetectable object. 3322 // It can be an undetectable object.
3405 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 3323 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
3406 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 3324 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
3407 Immediate(1 << Map::kIsUndetectable)); 3325 Immediate(1 << Map::kIsUndetectable));
3408 Split(not_zero, if_true, if_false, fall_through); 3326 Split(not_zero, if_true, if_false, fall_through);
3409 } 3327 }
3410 Apply(context_, if_true, if_false); 3328 context()->Plug(if_true, if_false);
3411 } 3329 }
3412 3330
3413 3331
3414 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 3332 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
3415 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 3333 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
3416 Apply(context_, rax); 3334 context()->Plug(rax);
3417 } 3335 }
3418 3336
3419 3337
3420 Register FullCodeGenerator::result_register() { return rax; } 3338 Register FullCodeGenerator::result_register() { return rax; }
3421 3339
3422 3340
3423 Register FullCodeGenerator::context_register() { return rsi; } 3341 Register FullCodeGenerator::context_register() { return rsi; }
3424 3342
3425 3343
3426 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3344 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3467 __ ret(0); 3385 __ ret(0);
3468 } 3386 }
3469 3387
3470 3388
3471 #undef __ 3389 #undef __
3472 3390
3473 3391
3474 } } // namespace v8::internal 3392 } } // namespace v8::internal
3475 3393
3476 #endif // V8_TARGET_ARCH_X64 3394 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698