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

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

Powered by Google App Engine
This is Rietveld 408576698