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

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

Powered by Google App Engine
This is Rietveld 408576698