OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 398 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
399 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 399 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
400 codegen()->GetVar(result_register(), var); | 400 codegen()->GetVar(result_register(), var); |
401 __ push(result_register()); | 401 __ push(result_register()); |
402 } | 402 } |
403 | 403 |
404 | 404 |
405 void FullCodeGenerator::TestContext::Plug(Variable* var) const { | 405 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
406 // For simplicity we always test the accumulator register. | 406 // For simplicity we always test the accumulator register. |
407 codegen()->GetVar(result_register(), var); | 407 codegen()->GetVar(result_register(), var); |
408 codegen()->PrepareForBailoutBeforeSplit(false, NULL, NULL); | 408 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
409 codegen()->DoTest(this); | 409 codegen()->DoTest(this); |
410 } | 410 } |
411 | 411 |
412 | 412 |
413 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 413 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
414 } | 414 } |
415 | 415 |
416 | 416 |
417 void FullCodeGenerator::AccumulatorValueContext::Plug( | 417 void FullCodeGenerator::AccumulatorValueContext::Plug( |
418 Heap::RootListIndex index) const { | 418 Heap::RootListIndex index) const { |
419 __ LoadRoot(result_register(), index); | 419 __ LoadRoot(result_register(), index); |
420 } | 420 } |
421 | 421 |
422 | 422 |
423 void FullCodeGenerator::StackValueContext::Plug( | 423 void FullCodeGenerator::StackValueContext::Plug( |
424 Heap::RootListIndex index) const { | 424 Heap::RootListIndex index) const { |
425 __ LoadRoot(result_register(), index); | 425 __ LoadRoot(result_register(), index); |
426 __ push(result_register()); | 426 __ push(result_register()); |
427 } | 427 } |
428 | 428 |
429 | 429 |
430 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { | 430 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { |
431 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, | 431 codegen()->PrepareForBailoutBeforeSplit(condition(), |
432 true, | 432 true, |
433 true_label_, | 433 true_label_, |
434 false_label_); | 434 false_label_); |
435 if (index == Heap::kUndefinedValueRootIndex || | 435 if (index == Heap::kUndefinedValueRootIndex || |
436 index == Heap::kNullValueRootIndex || | 436 index == Heap::kNullValueRootIndex || |
437 index == Heap::kFalseValueRootIndex) { | 437 index == Heap::kFalseValueRootIndex) { |
438 if (false_label_ != fall_through_) __ Branch(false_label_); | 438 if (false_label_ != fall_through_) __ Branch(false_label_); |
439 } else if (index == Heap::kTrueValueRootIndex) { | 439 } else if (index == Heap::kTrueValueRootIndex) { |
440 if (true_label_ != fall_through_) __ Branch(true_label_); | 440 if (true_label_ != fall_through_) __ Branch(true_label_); |
441 } else { | 441 } else { |
(...skipping 14 matching lines...) Expand all Loading... |
456 | 456 |
457 | 457 |
458 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { | 458 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { |
459 // Immediates cannot be pushed directly. | 459 // Immediates cannot be pushed directly. |
460 __ li(result_register(), Operand(lit)); | 460 __ li(result_register(), Operand(lit)); |
461 __ push(result_register()); | 461 __ push(result_register()); |
462 } | 462 } |
463 | 463 |
464 | 464 |
465 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 465 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
466 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, | 466 codegen()->PrepareForBailoutBeforeSplit(condition(), |
467 true, | 467 true, |
468 true_label_, | 468 true_label_, |
469 false_label_); | 469 false_label_); |
470 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. | 470 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. |
471 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { | 471 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
472 if (false_label_ != fall_through_) __ Branch(false_label_); | 472 if (false_label_ != fall_through_) __ Branch(false_label_); |
473 } else if (lit->IsTrue() || lit->IsJSObject()) { | 473 } else if (lit->IsTrue() || lit->IsJSObject()) { |
474 if (true_label_ != fall_through_) __ Branch(true_label_); | 474 if (true_label_ != fall_through_) __ Branch(true_label_); |
475 } else if (lit->IsString()) { | 475 } else if (lit->IsString()) { |
476 if (String::cast(*lit)->length() == 0) { | 476 if (String::cast(*lit)->length() == 0) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 __ sw(reg, MemOperand(sp, 0)); | 515 __ sw(reg, MemOperand(sp, 0)); |
516 } | 516 } |
517 | 517 |
518 | 518 |
519 void FullCodeGenerator::TestContext::DropAndPlug(int count, | 519 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
520 Register reg) const { | 520 Register reg) const { |
521 ASSERT(count > 0); | 521 ASSERT(count > 0); |
522 // For simplicity we always test the accumulator register. | 522 // For simplicity we always test the accumulator register. |
523 __ Drop(count); | 523 __ Drop(count); |
524 __ Move(result_register(), reg); | 524 __ Move(result_register(), reg); |
525 codegen()->PrepareForBailoutBeforeSplit(false, NULL, NULL); | 525 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
526 codegen()->DoTest(this); | 526 codegen()->DoTest(this); |
527 } | 527 } |
528 | 528 |
529 | 529 |
530 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, | 530 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
531 Label* materialize_false) const { | 531 Label* materialize_false) const { |
532 ASSERT(materialize_true == materialize_false); | 532 ASSERT(materialize_true == materialize_false); |
533 __ bind(materialize_true); | 533 __ bind(materialize_true); |
534 } | 534 } |
535 | 535 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 | 582 |
583 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { | 583 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
584 Heap::RootListIndex value_root_index = | 584 Heap::RootListIndex value_root_index = |
585 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 585 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
586 __ LoadRoot(at, value_root_index); | 586 __ LoadRoot(at, value_root_index); |
587 __ push(at); | 587 __ push(at); |
588 } | 588 } |
589 | 589 |
590 | 590 |
591 void FullCodeGenerator::TestContext::Plug(bool flag) const { | 591 void FullCodeGenerator::TestContext::Plug(bool flag) const { |
592 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, | 592 codegen()->PrepareForBailoutBeforeSplit(condition(), |
593 true, | 593 true, |
594 true_label_, | 594 true_label_, |
595 false_label_); | 595 false_label_); |
596 if (flag) { | 596 if (flag) { |
597 if (true_label_ != fall_through_) __ Branch(true_label_); | 597 if (true_label_ != fall_through_) __ Branch(true_label_); |
598 } else { | 598 } else { |
599 if (false_label_ != fall_through_) __ Branch(false_label_); | 599 if (false_label_ != fall_through_) __ Branch(false_label_); |
600 } | 600 } |
601 } | 601 } |
602 | 602 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 __ RecordWriteContextSlot(scratch0, | 685 __ RecordWriteContextSlot(scratch0, |
686 location.offset(), | 686 location.offset(), |
687 src, | 687 src, |
688 scratch1, | 688 scratch1, |
689 kRAHasBeenSaved, | 689 kRAHasBeenSaved, |
690 kDontSaveFPRegs); | 690 kDontSaveFPRegs); |
691 } | 691 } |
692 } | 692 } |
693 | 693 |
694 | 694 |
695 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, | 695 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, |
696 bool should_normalize, | 696 bool should_normalize, |
697 Label* if_true, | 697 Label* if_true, |
698 Label* if_false) { | 698 Label* if_false) { |
699 // Only prepare for bailouts before splits if we're in a test | 699 // Only prepare for bailouts before splits if we're in a test |
700 // context. Otherwise, we let the Visit function deal with the | 700 // context. Otherwise, we let the Visit function deal with the |
701 // preparation to avoid preparing with the same AST id twice. | 701 // preparation to avoid preparing with the same AST id twice. |
702 if (!context()->IsTest() || !info_->IsOptimizable()) return; | 702 if (!context()->IsTest() || !info_->IsOptimizable()) return; |
703 | 703 |
704 Label skip; | 704 Label skip; |
705 if (should_normalize) __ Branch(&skip); | 705 if (should_normalize) __ Branch(&skip); |
706 | 706 PrepareForBailout(expr, TOS_REG); |
707 ForwardBailoutStack* current = forward_bailout_stack_; | |
708 while (current != NULL) { | |
709 PrepareForBailout(current->expr(), state); | |
710 current = current->parent(); | |
711 } | |
712 | |
713 if (should_normalize) { | 707 if (should_normalize) { |
714 __ LoadRoot(t0, Heap::kTrueValueRootIndex); | 708 __ LoadRoot(t0, Heap::kTrueValueRootIndex); |
715 Split(eq, a0, Operand(t0), if_true, if_false, NULL); | 709 Split(eq, a0, Operand(t0), if_true, if_false, NULL); |
716 __ bind(&skip); | 710 __ bind(&skip); |
717 } | 711 } |
718 } | 712 } |
719 | 713 |
720 | 714 |
721 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, | 715 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, |
722 VariableMode mode, | 716 VariableMode mode, |
(...skipping 1671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2394 __ li(a0, Operand(arg_count)); | 2388 __ li(a0, Operand(arg_count)); |
2395 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); | 2389 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); |
2396 | 2390 |
2397 Handle<Code> construct_builtin = | 2391 Handle<Code> construct_builtin = |
2398 isolate()->builtins()->JSConstructCall(); | 2392 isolate()->builtins()->JSConstructCall(); |
2399 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 2393 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
2400 context()->Plug(v0); | 2394 context()->Plug(v0); |
2401 } | 2395 } |
2402 | 2396 |
2403 | 2397 |
2404 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { | 2398 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
| 2399 ZoneList<Expression*>* args = expr->arguments(); |
2405 ASSERT(args->length() == 1); | 2400 ASSERT(args->length() == 1); |
2406 | 2401 |
2407 VisitForAccumulatorValue(args->at(0)); | 2402 VisitForAccumulatorValue(args->at(0)); |
2408 | 2403 |
2409 Label materialize_true, materialize_false; | 2404 Label materialize_true, materialize_false; |
2410 Label* if_true = NULL; | 2405 Label* if_true = NULL; |
2411 Label* if_false = NULL; | 2406 Label* if_false = NULL; |
2412 Label* fall_through = NULL; | 2407 Label* fall_through = NULL; |
2413 context()->PrepareTest(&materialize_true, &materialize_false, | 2408 context()->PrepareTest(&materialize_true, &materialize_false, |
2414 &if_true, &if_false, &fall_through); | 2409 &if_true, &if_false, &fall_through); |
2415 | 2410 |
2416 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2411 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2417 __ And(t0, v0, Operand(kSmiTagMask)); | 2412 __ And(t0, v0, Operand(kSmiTagMask)); |
2418 Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through); | 2413 Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through); |
2419 | 2414 |
2420 context()->Plug(if_true, if_false); | 2415 context()->Plug(if_true, if_false); |
2421 } | 2416 } |
2422 | 2417 |
2423 | 2418 |
2424 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { | 2419 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { |
| 2420 ZoneList<Expression*>* args = expr->arguments(); |
2425 ASSERT(args->length() == 1); | 2421 ASSERT(args->length() == 1); |
2426 | 2422 |
2427 VisitForAccumulatorValue(args->at(0)); | 2423 VisitForAccumulatorValue(args->at(0)); |
2428 | 2424 |
2429 Label materialize_true, materialize_false; | 2425 Label materialize_true, materialize_false; |
2430 Label* if_true = NULL; | 2426 Label* if_true = NULL; |
2431 Label* if_false = NULL; | 2427 Label* if_false = NULL; |
2432 Label* fall_through = NULL; | 2428 Label* fall_through = NULL; |
2433 context()->PrepareTest(&materialize_true, &materialize_false, | 2429 context()->PrepareTest(&materialize_true, &materialize_false, |
2434 &if_true, &if_false, &fall_through); | 2430 &if_true, &if_false, &fall_through); |
2435 | 2431 |
2436 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2432 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2437 __ And(at, v0, Operand(kSmiTagMask | 0x80000000)); | 2433 __ And(at, v0, Operand(kSmiTagMask | 0x80000000)); |
2438 Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through); | 2434 Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through); |
2439 | 2435 |
2440 context()->Plug(if_true, if_false); | 2436 context()->Plug(if_true, if_false); |
2441 } | 2437 } |
2442 | 2438 |
2443 | 2439 |
2444 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { | 2440 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { |
| 2441 ZoneList<Expression*>* args = expr->arguments(); |
2445 ASSERT(args->length() == 1); | 2442 ASSERT(args->length() == 1); |
2446 | 2443 |
2447 VisitForAccumulatorValue(args->at(0)); | 2444 VisitForAccumulatorValue(args->at(0)); |
2448 | 2445 |
2449 Label materialize_true, materialize_false; | 2446 Label materialize_true, materialize_false; |
2450 Label* if_true = NULL; | 2447 Label* if_true = NULL; |
2451 Label* if_false = NULL; | 2448 Label* if_false = NULL; |
2452 Label* fall_through = NULL; | 2449 Label* fall_through = NULL; |
2453 context()->PrepareTest(&materialize_true, &materialize_false, | 2450 context()->PrepareTest(&materialize_true, &materialize_false, |
2454 &if_true, &if_false, &fall_through); | 2451 &if_true, &if_false, &fall_through); |
2455 | 2452 |
2456 __ JumpIfSmi(v0, if_false); | 2453 __ JumpIfSmi(v0, if_false); |
2457 __ LoadRoot(at, Heap::kNullValueRootIndex); | 2454 __ LoadRoot(at, Heap::kNullValueRootIndex); |
2458 __ Branch(if_true, eq, v0, Operand(at)); | 2455 __ Branch(if_true, eq, v0, Operand(at)); |
2459 __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); | 2456 __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); |
2460 // Undetectable objects behave like undefined when tested with typeof. | 2457 // Undetectable objects behave like undefined when tested with typeof. |
2461 __ lbu(a1, FieldMemOperand(a2, Map::kBitFieldOffset)); | 2458 __ lbu(a1, FieldMemOperand(a2, Map::kBitFieldOffset)); |
2462 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); | 2459 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); |
2463 __ Branch(if_false, ne, at, Operand(zero_reg)); | 2460 __ Branch(if_false, ne, at, Operand(zero_reg)); |
2464 __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset)); | 2461 __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset)); |
2465 __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2462 __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
2466 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2463 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2467 Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE), | 2464 Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE), |
2468 if_true, if_false, fall_through); | 2465 if_true, if_false, fall_through); |
2469 | 2466 |
2470 context()->Plug(if_true, if_false); | 2467 context()->Plug(if_true, if_false); |
2471 } | 2468 } |
2472 | 2469 |
2473 | 2470 |
2474 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { | 2471 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { |
| 2472 ZoneList<Expression*>* args = expr->arguments(); |
2475 ASSERT(args->length() == 1); | 2473 ASSERT(args->length() == 1); |
2476 | 2474 |
2477 VisitForAccumulatorValue(args->at(0)); | 2475 VisitForAccumulatorValue(args->at(0)); |
2478 | 2476 |
2479 Label materialize_true, materialize_false; | 2477 Label materialize_true, materialize_false; |
2480 Label* if_true = NULL; | 2478 Label* if_true = NULL; |
2481 Label* if_false = NULL; | 2479 Label* if_false = NULL; |
2482 Label* fall_through = NULL; | 2480 Label* fall_through = NULL; |
2483 context()->PrepareTest(&materialize_true, &materialize_false, | 2481 context()->PrepareTest(&materialize_true, &materialize_false, |
2484 &if_true, &if_false, &fall_through); | 2482 &if_true, &if_false, &fall_through); |
2485 | 2483 |
2486 __ JumpIfSmi(v0, if_false); | 2484 __ JumpIfSmi(v0, if_false); |
2487 __ GetObjectType(v0, a1, a1); | 2485 __ GetObjectType(v0, a1, a1); |
2488 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2486 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2489 Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE), | 2487 Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE), |
2490 if_true, if_false, fall_through); | 2488 if_true, if_false, fall_through); |
2491 | 2489 |
2492 context()->Plug(if_true, if_false); | 2490 context()->Plug(if_true, if_false); |
2493 } | 2491 } |
2494 | 2492 |
2495 | 2493 |
2496 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 2494 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { |
| 2495 ZoneList<Expression*>* args = expr->arguments(); |
2497 ASSERT(args->length() == 1); | 2496 ASSERT(args->length() == 1); |
2498 | 2497 |
2499 VisitForAccumulatorValue(args->at(0)); | 2498 VisitForAccumulatorValue(args->at(0)); |
2500 | 2499 |
2501 Label materialize_true, materialize_false; | 2500 Label materialize_true, materialize_false; |
2502 Label* if_true = NULL; | 2501 Label* if_true = NULL; |
2503 Label* if_false = NULL; | 2502 Label* if_false = NULL; |
2504 Label* fall_through = NULL; | 2503 Label* fall_through = NULL; |
2505 context()->PrepareTest(&materialize_true, &materialize_false, | 2504 context()->PrepareTest(&materialize_true, &materialize_false, |
2506 &if_true, &if_false, &fall_through); | 2505 &if_true, &if_false, &fall_through); |
2507 | 2506 |
2508 __ JumpIfSmi(v0, if_false); | 2507 __ JumpIfSmi(v0, if_false); |
2509 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); | 2508 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); |
2510 __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset)); | 2509 __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset)); |
2511 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); | 2510 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); |
2512 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2511 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2513 Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through); | 2512 Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through); |
2514 | 2513 |
2515 context()->Plug(if_true, if_false); | 2514 context()->Plug(if_true, if_false); |
2516 } | 2515 } |
2517 | 2516 |
2518 | 2517 |
2519 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 2518 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
2520 ZoneList<Expression*>* args) { | 2519 CallRuntime* expr) { |
2521 | 2520 ZoneList<Expression*>* args = expr->arguments(); |
2522 ASSERT(args->length() == 1); | 2521 ASSERT(args->length() == 1); |
2523 | 2522 |
2524 VisitForAccumulatorValue(args->at(0)); | 2523 VisitForAccumulatorValue(args->at(0)); |
2525 | 2524 |
2526 Label materialize_true, materialize_false; | 2525 Label materialize_true, materialize_false; |
2527 Label* if_true = NULL; | 2526 Label* if_true = NULL; |
2528 Label* if_false = NULL; | 2527 Label* if_false = NULL; |
2529 Label* fall_through = NULL; | 2528 Label* fall_through = NULL; |
2530 context()->PrepareTest(&materialize_true, &materialize_false, | 2529 context()->PrepareTest(&materialize_true, &materialize_false, |
2531 &if_true, &if_false, &fall_through); | 2530 &if_true, &if_false, &fall_through); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2587 __ lw(a3, ContextOperand(a3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); | 2586 __ lw(a3, ContextOperand(a3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
2588 __ Branch(if_false, ne, a2, Operand(a3)); | 2587 __ Branch(if_false, ne, a2, Operand(a3)); |
2589 | 2588 |
2590 // Set the bit in the map to indicate that it has been checked safe for | 2589 // Set the bit in the map to indicate that it has been checked safe for |
2591 // default valueOf and set true result. | 2590 // default valueOf and set true result. |
2592 __ lbu(a2, FieldMemOperand(a1, Map::kBitField2Offset)); | 2591 __ lbu(a2, FieldMemOperand(a1, Map::kBitField2Offset)); |
2593 __ Or(a2, a2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); | 2592 __ Or(a2, a2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
2594 __ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset)); | 2593 __ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset)); |
2595 __ jmp(if_true); | 2594 __ jmp(if_true); |
2596 | 2595 |
2597 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2596 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2598 context()->Plug(if_true, if_false); | 2597 context()->Plug(if_true, if_false); |
2599 } | 2598 } |
2600 | 2599 |
2601 | 2600 |
2602 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { | 2601 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { |
| 2602 ZoneList<Expression*>* args = expr->arguments(); |
2603 ASSERT(args->length() == 1); | 2603 ASSERT(args->length() == 1); |
2604 | 2604 |
2605 VisitForAccumulatorValue(args->at(0)); | 2605 VisitForAccumulatorValue(args->at(0)); |
2606 | 2606 |
2607 Label materialize_true, materialize_false; | 2607 Label materialize_true, materialize_false; |
2608 Label* if_true = NULL; | 2608 Label* if_true = NULL; |
2609 Label* if_false = NULL; | 2609 Label* if_false = NULL; |
2610 Label* fall_through = NULL; | 2610 Label* fall_through = NULL; |
2611 context()->PrepareTest(&materialize_true, &materialize_false, | 2611 context()->PrepareTest(&materialize_true, &materialize_false, |
2612 &if_true, &if_false, &fall_through); | 2612 &if_true, &if_false, &fall_through); |
2613 | 2613 |
2614 __ JumpIfSmi(v0, if_false); | 2614 __ JumpIfSmi(v0, if_false); |
2615 __ GetObjectType(v0, a1, a2); | 2615 __ GetObjectType(v0, a1, a2); |
2616 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2616 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2617 __ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE)); | 2617 __ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE)); |
2618 __ Branch(if_false); | 2618 __ Branch(if_false); |
2619 | 2619 |
2620 context()->Plug(if_true, if_false); | 2620 context()->Plug(if_true, if_false); |
2621 } | 2621 } |
2622 | 2622 |
2623 | 2623 |
2624 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { | 2624 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { |
| 2625 ZoneList<Expression*>* args = expr->arguments(); |
2625 ASSERT(args->length() == 1); | 2626 ASSERT(args->length() == 1); |
2626 | 2627 |
2627 VisitForAccumulatorValue(args->at(0)); | 2628 VisitForAccumulatorValue(args->at(0)); |
2628 | 2629 |
2629 Label materialize_true, materialize_false; | 2630 Label materialize_true, materialize_false; |
2630 Label* if_true = NULL; | 2631 Label* if_true = NULL; |
2631 Label* if_false = NULL; | 2632 Label* if_false = NULL; |
2632 Label* fall_through = NULL; | 2633 Label* fall_through = NULL; |
2633 context()->PrepareTest(&materialize_true, &materialize_false, | 2634 context()->PrepareTest(&materialize_true, &materialize_false, |
2634 &if_true, &if_false, &fall_through); | 2635 &if_true, &if_false, &fall_through); |
2635 | 2636 |
2636 __ JumpIfSmi(v0, if_false); | 2637 __ JumpIfSmi(v0, if_false); |
2637 __ GetObjectType(v0, a1, a1); | 2638 __ GetObjectType(v0, a1, a1); |
2638 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2639 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2639 Split(eq, a1, Operand(JS_ARRAY_TYPE), | 2640 Split(eq, a1, Operand(JS_ARRAY_TYPE), |
2640 if_true, if_false, fall_through); | 2641 if_true, if_false, fall_through); |
2641 | 2642 |
2642 context()->Plug(if_true, if_false); | 2643 context()->Plug(if_true, if_false); |
2643 } | 2644 } |
2644 | 2645 |
2645 | 2646 |
2646 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { | 2647 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { |
| 2648 ZoneList<Expression*>* args = expr->arguments(); |
2647 ASSERT(args->length() == 1); | 2649 ASSERT(args->length() == 1); |
2648 | 2650 |
2649 VisitForAccumulatorValue(args->at(0)); | 2651 VisitForAccumulatorValue(args->at(0)); |
2650 | 2652 |
2651 Label materialize_true, materialize_false; | 2653 Label materialize_true, materialize_false; |
2652 Label* if_true = NULL; | 2654 Label* if_true = NULL; |
2653 Label* if_false = NULL; | 2655 Label* if_false = NULL; |
2654 Label* fall_through = NULL; | 2656 Label* fall_through = NULL; |
2655 context()->PrepareTest(&materialize_true, &materialize_false, | 2657 context()->PrepareTest(&materialize_true, &materialize_false, |
2656 &if_true, &if_false, &fall_through); | 2658 &if_true, &if_false, &fall_through); |
2657 | 2659 |
2658 __ JumpIfSmi(v0, if_false); | 2660 __ JumpIfSmi(v0, if_false); |
2659 __ GetObjectType(v0, a1, a1); | 2661 __ GetObjectType(v0, a1, a1); |
2660 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2662 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2661 Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through); | 2663 Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through); |
2662 | 2664 |
2663 context()->Plug(if_true, if_false); | 2665 context()->Plug(if_true, if_false); |
2664 } | 2666 } |
2665 | 2667 |
2666 | 2668 |
2667 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { | 2669 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { |
2668 ASSERT(args->length() == 0); | 2670 ASSERT(expr->arguments()->length() == 0); |
2669 | 2671 |
2670 Label materialize_true, materialize_false; | 2672 Label materialize_true, materialize_false; |
2671 Label* if_true = NULL; | 2673 Label* if_true = NULL; |
2672 Label* if_false = NULL; | 2674 Label* if_false = NULL; |
2673 Label* fall_through = NULL; | 2675 Label* fall_through = NULL; |
2674 context()->PrepareTest(&materialize_true, &materialize_false, | 2676 context()->PrepareTest(&materialize_true, &materialize_false, |
2675 &if_true, &if_false, &fall_through); | 2677 &if_true, &if_false, &fall_through); |
2676 | 2678 |
2677 // Get the frame pointer for the calling frame. | 2679 // Get the frame pointer for the calling frame. |
2678 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 2680 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
2679 | 2681 |
2680 // Skip the arguments adaptor frame if it exists. | 2682 // Skip the arguments adaptor frame if it exists. |
2681 Label check_frame_marker; | 2683 Label check_frame_marker; |
2682 __ lw(a1, MemOperand(a2, StandardFrameConstants::kContextOffset)); | 2684 __ lw(a1, MemOperand(a2, StandardFrameConstants::kContextOffset)); |
2683 __ Branch(&check_frame_marker, ne, | 2685 __ Branch(&check_frame_marker, ne, |
2684 a1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2686 a1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
2685 __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); | 2687 __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); |
2686 | 2688 |
2687 // Check the marker in the calling frame. | 2689 // Check the marker in the calling frame. |
2688 __ bind(&check_frame_marker); | 2690 __ bind(&check_frame_marker); |
2689 __ lw(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset)); | 2691 __ lw(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset)); |
2690 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2692 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2691 Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)), | 2693 Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)), |
2692 if_true, if_false, fall_through); | 2694 if_true, if_false, fall_through); |
2693 | 2695 |
2694 context()->Plug(if_true, if_false); | 2696 context()->Plug(if_true, if_false); |
2695 } | 2697 } |
2696 | 2698 |
2697 | 2699 |
2698 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { | 2700 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { |
| 2701 ZoneList<Expression*>* args = expr->arguments(); |
2699 ASSERT(args->length() == 2); | 2702 ASSERT(args->length() == 2); |
2700 | 2703 |
2701 // Load the two objects into registers and perform the comparison. | 2704 // Load the two objects into registers and perform the comparison. |
2702 VisitForStackValue(args->at(0)); | 2705 VisitForStackValue(args->at(0)); |
2703 VisitForAccumulatorValue(args->at(1)); | 2706 VisitForAccumulatorValue(args->at(1)); |
2704 | 2707 |
2705 Label materialize_true, materialize_false; | 2708 Label materialize_true, materialize_false; |
2706 Label* if_true = NULL; | 2709 Label* if_true = NULL; |
2707 Label* if_false = NULL; | 2710 Label* if_false = NULL; |
2708 Label* fall_through = NULL; | 2711 Label* fall_through = NULL; |
2709 context()->PrepareTest(&materialize_true, &materialize_false, | 2712 context()->PrepareTest(&materialize_true, &materialize_false, |
2710 &if_true, &if_false, &fall_through); | 2713 &if_true, &if_false, &fall_through); |
2711 | 2714 |
2712 __ pop(a1); | 2715 __ pop(a1); |
2713 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 2716 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2714 Split(eq, v0, Operand(a1), if_true, if_false, fall_through); | 2717 Split(eq, v0, Operand(a1), if_true, if_false, fall_through); |
2715 | 2718 |
2716 context()->Plug(if_true, if_false); | 2719 context()->Plug(if_true, if_false); |
2717 } | 2720 } |
2718 | 2721 |
2719 | 2722 |
2720 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 2723 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { |
| 2724 ZoneList<Expression*>* args = expr->arguments(); |
2721 ASSERT(args->length() == 1); | 2725 ASSERT(args->length() == 1); |
2722 | 2726 |
2723 // ArgumentsAccessStub expects the key in a1 and the formal | 2727 // ArgumentsAccessStub expects the key in a1 and the formal |
2724 // parameter count in a0. | 2728 // parameter count in a0. |
2725 VisitForAccumulatorValue(args->at(0)); | 2729 VisitForAccumulatorValue(args->at(0)); |
2726 __ mov(a1, v0); | 2730 __ mov(a1, v0); |
2727 __ li(a0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); | 2731 __ li(a0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); |
2728 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | 2732 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); |
2729 __ CallStub(&stub); | 2733 __ CallStub(&stub); |
2730 context()->Plug(v0); | 2734 context()->Plug(v0); |
2731 } | 2735 } |
2732 | 2736 |
2733 | 2737 |
2734 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { | 2738 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { |
2735 ASSERT(args->length() == 0); | 2739 ASSERT(expr->arguments()->length() == 0); |
2736 | |
2737 Label exit; | 2740 Label exit; |
2738 // Get the number of formal parameters. | 2741 // Get the number of formal parameters. |
2739 __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); | 2742 __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); |
2740 | 2743 |
2741 // Check if the calling frame is an arguments adaptor frame. | 2744 // Check if the calling frame is an arguments adaptor frame. |
2742 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 2745 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
2743 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); | 2746 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); |
2744 __ Branch(&exit, ne, a3, | 2747 __ Branch(&exit, ne, a3, |
2745 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2748 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
2746 | 2749 |
2747 // Arguments adaptor case: Read the arguments length from the | 2750 // Arguments adaptor case: Read the arguments length from the |
2748 // adaptor frame. | 2751 // adaptor frame. |
2749 __ lw(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2752 __ lw(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
2750 | 2753 |
2751 __ bind(&exit); | 2754 __ bind(&exit); |
2752 context()->Plug(v0); | 2755 context()->Plug(v0); |
2753 } | 2756 } |
2754 | 2757 |
2755 | 2758 |
2756 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { | 2759 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { |
| 2760 ZoneList<Expression*>* args = expr->arguments(); |
2757 ASSERT(args->length() == 1); | 2761 ASSERT(args->length() == 1); |
2758 Label done, null, function, non_function_constructor; | 2762 Label done, null, function, non_function_constructor; |
2759 | 2763 |
2760 VisitForAccumulatorValue(args->at(0)); | 2764 VisitForAccumulatorValue(args->at(0)); |
2761 | 2765 |
2762 // If the object is a smi, we return null. | 2766 // If the object is a smi, we return null. |
2763 __ JumpIfSmi(v0, &null); | 2767 __ JumpIfSmi(v0, &null); |
2764 | 2768 |
2765 // Check that the object is a JS object but take special care of JS | 2769 // Check that the object is a JS object but take special care of JS |
2766 // functions to make sure they have 'Function' as their class. | 2770 // functions to make sure they have 'Function' as their class. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2805 __ bind(&null); | 2809 __ bind(&null); |
2806 __ LoadRoot(v0, Heap::kNullValueRootIndex); | 2810 __ LoadRoot(v0, Heap::kNullValueRootIndex); |
2807 | 2811 |
2808 // All done. | 2812 // All done. |
2809 __ bind(&done); | 2813 __ bind(&done); |
2810 | 2814 |
2811 context()->Plug(v0); | 2815 context()->Plug(v0); |
2812 } | 2816 } |
2813 | 2817 |
2814 | 2818 |
2815 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { | 2819 void FullCodeGenerator::EmitLog(CallRuntime* expr) { |
2816 // Conditionally generate a log call. | 2820 // Conditionally generate a log call. |
2817 // Args: | 2821 // Args: |
2818 // 0 (literal string): The type of logging (corresponds to the flags). | 2822 // 0 (literal string): The type of logging (corresponds to the flags). |
2819 // This is used to determine whether or not to generate the log call. | 2823 // This is used to determine whether or not to generate the log call. |
2820 // 1 (string): Format string. Access the string at argument index 2 | 2824 // 1 (string): Format string. Access the string at argument index 2 |
2821 // with '%2s' (see Logger::LogRuntime for all the formats). | 2825 // with '%2s' (see Logger::LogRuntime for all the formats). |
2822 // 2 (array): Arguments to the format string. | 2826 // 2 (array): Arguments to the format string. |
| 2827 ZoneList<Expression*>* args = expr->arguments(); |
2823 ASSERT_EQ(args->length(), 3); | 2828 ASSERT_EQ(args->length(), 3); |
2824 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { | 2829 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { |
2825 VisitForStackValue(args->at(1)); | 2830 VisitForStackValue(args->at(1)); |
2826 VisitForStackValue(args->at(2)); | 2831 VisitForStackValue(args->at(2)); |
2827 __ CallRuntime(Runtime::kLog, 2); | 2832 __ CallRuntime(Runtime::kLog, 2); |
2828 } | 2833 } |
2829 | 2834 |
2830 // Finally, we're expected to leave a value on the top of the stack. | 2835 // Finally, we're expected to leave a value on the top of the stack. |
2831 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 2836 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
2832 context()->Plug(v0); | 2837 context()->Plug(v0); |
2833 } | 2838 } |
2834 | 2839 |
2835 | 2840 |
2836 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { | 2841 void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) { |
2837 ASSERT(args->length() == 0); | 2842 ASSERT(expr->arguments()->length() == 0); |
2838 | |
2839 Label slow_allocate_heapnumber; | 2843 Label slow_allocate_heapnumber; |
2840 Label heapnumber_allocated; | 2844 Label heapnumber_allocated; |
2841 | 2845 |
2842 // Save the new heap number in callee-saved register s0, since | 2846 // Save the new heap number in callee-saved register s0, since |
2843 // we call out to external C code below. | 2847 // we call out to external C code below. |
2844 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); | 2848 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); |
2845 __ AllocateHeapNumber(s0, a1, a2, t6, &slow_allocate_heapnumber); | 2849 __ AllocateHeapNumber(s0, a1, a2, t6, &slow_allocate_heapnumber); |
2846 __ jmp(&heapnumber_allocated); | 2850 __ jmp(&heapnumber_allocated); |
2847 | 2851 |
2848 __ bind(&slow_allocate_heapnumber); | 2852 __ bind(&slow_allocate_heapnumber); |
(...skipping 30 matching lines...) Expand all Loading... |
2879 __ lw(a1, ContextOperand(cp, Context::GLOBAL_INDEX)); | 2883 __ lw(a1, ContextOperand(cp, Context::GLOBAL_INDEX)); |
2880 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalContextOffset)); | 2884 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalContextOffset)); |
2881 __ CallCFunction( | 2885 __ CallCFunction( |
2882 ExternalReference::fill_heap_number_with_random_function(isolate()), 2); | 2886 ExternalReference::fill_heap_number_with_random_function(isolate()), 2); |
2883 } | 2887 } |
2884 | 2888 |
2885 context()->Plug(v0); | 2889 context()->Plug(v0); |
2886 } | 2890 } |
2887 | 2891 |
2888 | 2892 |
2889 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { | 2893 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { |
2890 // Load the arguments on the stack and call the stub. | 2894 // Load the arguments on the stack and call the stub. |
2891 SubStringStub stub; | 2895 SubStringStub stub; |
| 2896 ZoneList<Expression*>* args = expr->arguments(); |
2892 ASSERT(args->length() == 3); | 2897 ASSERT(args->length() == 3); |
2893 VisitForStackValue(args->at(0)); | 2898 VisitForStackValue(args->at(0)); |
2894 VisitForStackValue(args->at(1)); | 2899 VisitForStackValue(args->at(1)); |
2895 VisitForStackValue(args->at(2)); | 2900 VisitForStackValue(args->at(2)); |
2896 __ CallStub(&stub); | 2901 __ CallStub(&stub); |
2897 context()->Plug(v0); | 2902 context()->Plug(v0); |
2898 } | 2903 } |
2899 | 2904 |
2900 | 2905 |
2901 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { | 2906 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { |
2902 // Load the arguments on the stack and call the stub. | 2907 // Load the arguments on the stack and call the stub. |
2903 RegExpExecStub stub; | 2908 RegExpExecStub stub; |
| 2909 ZoneList<Expression*>* args = expr->arguments(); |
2904 ASSERT(args->length() == 4); | 2910 ASSERT(args->length() == 4); |
2905 VisitForStackValue(args->at(0)); | 2911 VisitForStackValue(args->at(0)); |
2906 VisitForStackValue(args->at(1)); | 2912 VisitForStackValue(args->at(1)); |
2907 VisitForStackValue(args->at(2)); | 2913 VisitForStackValue(args->at(2)); |
2908 VisitForStackValue(args->at(3)); | 2914 VisitForStackValue(args->at(3)); |
2909 __ CallStub(&stub); | 2915 __ CallStub(&stub); |
2910 context()->Plug(v0); | 2916 context()->Plug(v0); |
2911 } | 2917 } |
2912 | 2918 |
2913 | 2919 |
2914 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { | 2920 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { |
| 2921 ZoneList<Expression*>* args = expr->arguments(); |
2915 ASSERT(args->length() == 1); | 2922 ASSERT(args->length() == 1); |
2916 | 2923 |
2917 VisitForAccumulatorValue(args->at(0)); // Load the object. | 2924 VisitForAccumulatorValue(args->at(0)); // Load the object. |
2918 | 2925 |
2919 Label done; | 2926 Label done; |
2920 // If the object is a smi return the object. | 2927 // If the object is a smi return the object. |
2921 __ JumpIfSmi(v0, &done); | 2928 __ JumpIfSmi(v0, &done); |
2922 // If the object is not a value type, return the object. | 2929 // If the object is not a value type, return the object. |
2923 __ GetObjectType(v0, a1, a1); | 2930 __ GetObjectType(v0, a1, a1); |
2924 __ Branch(&done, ne, a1, Operand(JS_VALUE_TYPE)); | 2931 __ Branch(&done, ne, a1, Operand(JS_VALUE_TYPE)); |
2925 | 2932 |
2926 __ lw(v0, FieldMemOperand(v0, JSValue::kValueOffset)); | 2933 __ lw(v0, FieldMemOperand(v0, JSValue::kValueOffset)); |
2927 | 2934 |
2928 __ bind(&done); | 2935 __ bind(&done); |
2929 context()->Plug(v0); | 2936 context()->Plug(v0); |
2930 } | 2937 } |
2931 | 2938 |
2932 | 2939 |
2933 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { | 2940 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
2934 // Load the arguments on the stack and call the runtime function. | 2941 // Load the arguments on the stack and call the runtime function. |
| 2942 ZoneList<Expression*>* args = expr->arguments(); |
2935 ASSERT(args->length() == 2); | 2943 ASSERT(args->length() == 2); |
2936 VisitForStackValue(args->at(0)); | 2944 VisitForStackValue(args->at(0)); |
2937 VisitForStackValue(args->at(1)); | 2945 VisitForStackValue(args->at(1)); |
2938 MathPowStub stub; | 2946 MathPowStub stub; |
2939 __ CallStub(&stub); | 2947 __ CallStub(&stub); |
2940 context()->Plug(v0); | 2948 context()->Plug(v0); |
2941 } | 2949 } |
2942 | 2950 |
2943 | 2951 |
2944 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2952 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
| 2953 ZoneList<Expression*>* args = expr->arguments(); |
2945 ASSERT(args->length() == 2); | 2954 ASSERT(args->length() == 2); |
2946 | 2955 |
2947 VisitForStackValue(args->at(0)); // Load the object. | 2956 VisitForStackValue(args->at(0)); // Load the object. |
2948 VisitForAccumulatorValue(args->at(1)); // Load the value. | 2957 VisitForAccumulatorValue(args->at(1)); // Load the value. |
2949 __ pop(a1); // v0 = value. a1 = object. | 2958 __ pop(a1); // v0 = value. a1 = object. |
2950 | 2959 |
2951 Label done; | 2960 Label done; |
2952 // If the object is a smi, return the value. | 2961 // If the object is a smi, return the value. |
2953 __ JumpIfSmi(a1, &done); | 2962 __ JumpIfSmi(a1, &done); |
2954 | 2963 |
2955 // If the object is not a value type, return the value. | 2964 // If the object is not a value type, return the value. |
2956 __ GetObjectType(a1, a2, a2); | 2965 __ GetObjectType(a1, a2, a2); |
2957 __ Branch(&done, ne, a2, Operand(JS_VALUE_TYPE)); | 2966 __ Branch(&done, ne, a2, Operand(JS_VALUE_TYPE)); |
2958 | 2967 |
2959 // Store the value. | 2968 // Store the value. |
2960 __ sw(v0, FieldMemOperand(a1, JSValue::kValueOffset)); | 2969 __ sw(v0, FieldMemOperand(a1, JSValue::kValueOffset)); |
2961 // Update the write barrier. Save the value as it will be | 2970 // Update the write barrier. Save the value as it will be |
2962 // overwritten by the write barrier code and is needed afterward. | 2971 // overwritten by the write barrier code and is needed afterward. |
2963 __ mov(a2, v0); | 2972 __ mov(a2, v0); |
2964 __ RecordWriteField( | 2973 __ RecordWriteField( |
2965 a1, JSValue::kValueOffset, a2, a3, kRAHasBeenSaved, kDontSaveFPRegs); | 2974 a1, JSValue::kValueOffset, a2, a3, kRAHasBeenSaved, kDontSaveFPRegs); |
2966 | 2975 |
2967 __ bind(&done); | 2976 __ bind(&done); |
2968 context()->Plug(v0); | 2977 context()->Plug(v0); |
2969 } | 2978 } |
2970 | 2979 |
2971 | 2980 |
2972 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { | 2981 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
| 2982 ZoneList<Expression*>* args = expr->arguments(); |
2973 ASSERT_EQ(args->length(), 1); | 2983 ASSERT_EQ(args->length(), 1); |
2974 | 2984 |
2975 // Load the argument on the stack and call the stub. | 2985 // Load the argument on the stack and call the stub. |
2976 VisitForStackValue(args->at(0)); | 2986 VisitForStackValue(args->at(0)); |
2977 | 2987 |
2978 NumberToStringStub stub; | 2988 NumberToStringStub stub; |
2979 __ CallStub(&stub); | 2989 __ CallStub(&stub); |
2980 context()->Plug(v0); | 2990 context()->Plug(v0); |
2981 } | 2991 } |
2982 | 2992 |
2983 | 2993 |
2984 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { | 2994 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
| 2995 ZoneList<Expression*>* args = expr->arguments(); |
2985 ASSERT(args->length() == 1); | 2996 ASSERT(args->length() == 1); |
2986 | 2997 |
2987 VisitForAccumulatorValue(args->at(0)); | 2998 VisitForAccumulatorValue(args->at(0)); |
2988 | 2999 |
2989 Label done; | 3000 Label done; |
2990 StringCharFromCodeGenerator generator(v0, a1); | 3001 StringCharFromCodeGenerator generator(v0, a1); |
2991 generator.GenerateFast(masm_); | 3002 generator.GenerateFast(masm_); |
2992 __ jmp(&done); | 3003 __ jmp(&done); |
2993 | 3004 |
2994 NopRuntimeCallHelper call_helper; | 3005 NopRuntimeCallHelper call_helper; |
2995 generator.GenerateSlow(masm_, call_helper); | 3006 generator.GenerateSlow(masm_, call_helper); |
2996 | 3007 |
2997 __ bind(&done); | 3008 __ bind(&done); |
2998 context()->Plug(a1); | 3009 context()->Plug(a1); |
2999 } | 3010 } |
3000 | 3011 |
3001 | 3012 |
3002 void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { | 3013 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { |
| 3014 ZoneList<Expression*>* args = expr->arguments(); |
3003 ASSERT(args->length() == 2); | 3015 ASSERT(args->length() == 2); |
3004 | 3016 |
3005 VisitForStackValue(args->at(0)); | 3017 VisitForStackValue(args->at(0)); |
3006 VisitForAccumulatorValue(args->at(1)); | 3018 VisitForAccumulatorValue(args->at(1)); |
3007 __ mov(a0, result_register()); | 3019 __ mov(a0, result_register()); |
3008 | 3020 |
3009 Register object = a1; | 3021 Register object = a1; |
3010 Register index = a0; | 3022 Register index = a0; |
3011 Register scratch = a2; | 3023 Register scratch = a2; |
3012 Register result = v0; | 3024 Register result = v0; |
(...skipping 27 matching lines...) Expand all Loading... |
3040 __ jmp(&done); | 3052 __ jmp(&done); |
3041 | 3053 |
3042 NopRuntimeCallHelper call_helper; | 3054 NopRuntimeCallHelper call_helper; |
3043 generator.GenerateSlow(masm_, call_helper); | 3055 generator.GenerateSlow(masm_, call_helper); |
3044 | 3056 |
3045 __ bind(&done); | 3057 __ bind(&done); |
3046 context()->Plug(result); | 3058 context()->Plug(result); |
3047 } | 3059 } |
3048 | 3060 |
3049 | 3061 |
3050 void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { | 3062 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { |
| 3063 ZoneList<Expression*>* args = expr->arguments(); |
3051 ASSERT(args->length() == 2); | 3064 ASSERT(args->length() == 2); |
3052 | 3065 |
3053 VisitForStackValue(args->at(0)); | 3066 VisitForStackValue(args->at(0)); |
3054 VisitForAccumulatorValue(args->at(1)); | 3067 VisitForAccumulatorValue(args->at(1)); |
3055 __ mov(a0, result_register()); | 3068 __ mov(a0, result_register()); |
3056 | 3069 |
3057 Register object = a1; | 3070 Register object = a1; |
3058 Register index = a0; | 3071 Register index = a0; |
3059 Register scratch1 = a2; | 3072 Register scratch1 = a2; |
3060 Register scratch2 = a3; | 3073 Register scratch2 = a3; |
(...skipping 29 matching lines...) Expand all Loading... |
3090 __ jmp(&done); | 3103 __ jmp(&done); |
3091 | 3104 |
3092 NopRuntimeCallHelper call_helper; | 3105 NopRuntimeCallHelper call_helper; |
3093 generator.GenerateSlow(masm_, call_helper); | 3106 generator.GenerateSlow(masm_, call_helper); |
3094 | 3107 |
3095 __ bind(&done); | 3108 __ bind(&done); |
3096 context()->Plug(result); | 3109 context()->Plug(result); |
3097 } | 3110 } |
3098 | 3111 |
3099 | 3112 |
3100 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { | 3113 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { |
| 3114 ZoneList<Expression*>* args = expr->arguments(); |
3101 ASSERT_EQ(2, args->length()); | 3115 ASSERT_EQ(2, args->length()); |
3102 | |
3103 VisitForStackValue(args->at(0)); | 3116 VisitForStackValue(args->at(0)); |
3104 VisitForStackValue(args->at(1)); | 3117 VisitForStackValue(args->at(1)); |
3105 | 3118 |
3106 StringAddStub stub(NO_STRING_ADD_FLAGS); | 3119 StringAddStub stub(NO_STRING_ADD_FLAGS); |
3107 __ CallStub(&stub); | 3120 __ CallStub(&stub); |
3108 context()->Plug(v0); | 3121 context()->Plug(v0); |
3109 } | 3122 } |
3110 | 3123 |
3111 | 3124 |
3112 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { | 3125 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
| 3126 ZoneList<Expression*>* args = expr->arguments(); |
3113 ASSERT_EQ(2, args->length()); | 3127 ASSERT_EQ(2, args->length()); |
3114 | 3128 |
3115 VisitForStackValue(args->at(0)); | 3129 VisitForStackValue(args->at(0)); |
3116 VisitForStackValue(args->at(1)); | 3130 VisitForStackValue(args->at(1)); |
3117 | 3131 |
3118 StringCompareStub stub; | 3132 StringCompareStub stub; |
3119 __ CallStub(&stub); | 3133 __ CallStub(&stub); |
3120 context()->Plug(v0); | 3134 context()->Plug(v0); |
3121 } | 3135 } |
3122 | 3136 |
3123 | 3137 |
3124 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { | 3138 void FullCodeGenerator::EmitMathSin(CallRuntime* expr) { |
3125 // Load the argument on the stack and call the stub. | 3139 // Load the argument on the stack and call the stub. |
3126 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 3140 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
3127 TranscendentalCacheStub::TAGGED); | 3141 TranscendentalCacheStub::TAGGED); |
| 3142 ZoneList<Expression*>* args = expr->arguments(); |
3128 ASSERT(args->length() == 1); | 3143 ASSERT(args->length() == 1); |
3129 VisitForStackValue(args->at(0)); | 3144 VisitForStackValue(args->at(0)); |
3130 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. | 3145 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. |
3131 __ CallStub(&stub); | 3146 __ CallStub(&stub); |
3132 context()->Plug(v0); | 3147 context()->Plug(v0); |
3133 } | 3148 } |
3134 | 3149 |
3135 | 3150 |
3136 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { | 3151 void FullCodeGenerator::EmitMathCos(CallRuntime* expr) { |
3137 // Load the argument on the stack and call the stub. | 3152 // Load the argument on the stack and call the stub. |
3138 TranscendentalCacheStub stub(TranscendentalCache::COS, | 3153 TranscendentalCacheStub stub(TranscendentalCache::COS, |
3139 TranscendentalCacheStub::TAGGED); | 3154 TranscendentalCacheStub::TAGGED); |
| 3155 ZoneList<Expression*>* args = expr->arguments(); |
3140 ASSERT(args->length() == 1); | 3156 ASSERT(args->length() == 1); |
3141 VisitForStackValue(args->at(0)); | 3157 VisitForStackValue(args->at(0)); |
3142 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. | 3158 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. |
3143 __ CallStub(&stub); | 3159 __ CallStub(&stub); |
3144 context()->Plug(v0); | 3160 context()->Plug(v0); |
3145 } | 3161 } |
3146 | 3162 |
3147 | 3163 |
3148 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { | 3164 void FullCodeGenerator::EmitMathLog(CallRuntime* expr) { |
3149 // Load the argument on the stack and call the stub. | 3165 // Load the argument on the stack and call the stub. |
3150 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 3166 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
3151 TranscendentalCacheStub::TAGGED); | 3167 TranscendentalCacheStub::TAGGED); |
| 3168 ZoneList<Expression*>* args = expr->arguments(); |
3152 ASSERT(args->length() == 1); | 3169 ASSERT(args->length() == 1); |
3153 VisitForStackValue(args->at(0)); | 3170 VisitForStackValue(args->at(0)); |
3154 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. | 3171 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. |
3155 __ CallStub(&stub); | 3172 __ CallStub(&stub); |
3156 context()->Plug(v0); | 3173 context()->Plug(v0); |
3157 } | 3174 } |
3158 | 3175 |
3159 | 3176 |
3160 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { | 3177 void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) { |
3161 // Load the argument on the stack and call the runtime function. | 3178 // Load the argument on the stack and call the runtime function. |
| 3179 ZoneList<Expression*>* args = expr->arguments(); |
3162 ASSERT(args->length() == 1); | 3180 ASSERT(args->length() == 1); |
3163 VisitForStackValue(args->at(0)); | 3181 VisitForStackValue(args->at(0)); |
3164 __ CallRuntime(Runtime::kMath_sqrt, 1); | 3182 __ CallRuntime(Runtime::kMath_sqrt, 1); |
3165 context()->Plug(v0); | 3183 context()->Plug(v0); |
3166 } | 3184 } |
3167 | 3185 |
3168 | 3186 |
3169 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { | 3187 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { |
| 3188 ZoneList<Expression*>* args = expr->arguments(); |
3170 ASSERT(args->length() >= 2); | 3189 ASSERT(args->length() >= 2); |
3171 | 3190 |
3172 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 3191 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
3173 for (int i = 0; i < arg_count + 1; i++) { | 3192 for (int i = 0; i < arg_count + 1; i++) { |
3174 VisitForStackValue(args->at(i)); | 3193 VisitForStackValue(args->at(i)); |
3175 } | 3194 } |
3176 VisitForAccumulatorValue(args->last()); // Function. | 3195 VisitForAccumulatorValue(args->last()); // Function. |
3177 | 3196 |
3178 // InvokeFunction requires the function in a1. Move it in there. | 3197 // InvokeFunction requires the function in a1. Move it in there. |
3179 __ mov(a1, result_register()); | 3198 __ mov(a1, result_register()); |
3180 ParameterCount count(arg_count); | 3199 ParameterCount count(arg_count); |
3181 __ InvokeFunction(a1, count, CALL_FUNCTION, | 3200 __ InvokeFunction(a1, count, CALL_FUNCTION, |
3182 NullCallWrapper(), CALL_AS_METHOD); | 3201 NullCallWrapper(), CALL_AS_METHOD); |
3183 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3202 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3184 context()->Plug(v0); | 3203 context()->Plug(v0); |
3185 } | 3204 } |
3186 | 3205 |
3187 | 3206 |
3188 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { | 3207 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { |
3189 RegExpConstructResultStub stub; | 3208 RegExpConstructResultStub stub; |
| 3209 ZoneList<Expression*>* args = expr->arguments(); |
3190 ASSERT(args->length() == 3); | 3210 ASSERT(args->length() == 3); |
3191 VisitForStackValue(args->at(0)); | 3211 VisitForStackValue(args->at(0)); |
3192 VisitForStackValue(args->at(1)); | 3212 VisitForStackValue(args->at(1)); |
3193 VisitForStackValue(args->at(2)); | 3213 VisitForStackValue(args->at(2)); |
3194 __ CallStub(&stub); | 3214 __ CallStub(&stub); |
3195 context()->Plug(v0); | 3215 context()->Plug(v0); |
3196 } | 3216 } |
3197 | 3217 |
3198 | 3218 |
3199 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { | 3219 void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) { |
| 3220 ZoneList<Expression*>* args = expr->arguments(); |
3200 ASSERT(args->length() == 3); | 3221 ASSERT(args->length() == 3); |
3201 VisitForStackValue(args->at(0)); | 3222 VisitForStackValue(args->at(0)); |
3202 VisitForStackValue(args->at(1)); | 3223 VisitForStackValue(args->at(1)); |
3203 VisitForStackValue(args->at(2)); | 3224 VisitForStackValue(args->at(2)); |
3204 Label done; | 3225 Label done; |
3205 Label slow_case; | 3226 Label slow_case; |
3206 Register object = a0; | 3227 Register object = a0; |
3207 Register index1 = a1; | 3228 Register index1 = a1; |
3208 Register index2 = a2; | 3229 Register index2 = a2; |
3209 Register elements = a3; | 3230 Register elements = a3; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3286 __ jmp(&done); | 3307 __ jmp(&done); |
3287 | 3308 |
3288 __ bind(&slow_case); | 3309 __ bind(&slow_case); |
3289 __ CallRuntime(Runtime::kSwapElements, 3); | 3310 __ CallRuntime(Runtime::kSwapElements, 3); |
3290 | 3311 |
3291 __ bind(&done); | 3312 __ bind(&done); |
3292 context()->Plug(v0); | 3313 context()->Plug(v0); |
3293 } | 3314 } |
3294 | 3315 |
3295 | 3316 |
3296 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { | 3317 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { |
| 3318 ZoneList<Expression*>* args = expr->arguments(); |
3297 ASSERT_EQ(2, args->length()); | 3319 ASSERT_EQ(2, args->length()); |
3298 | 3320 |
3299 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3321 ASSERT_NE(NULL, args->at(0)->AsLiteral()); |
3300 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); | 3322 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); |
3301 | 3323 |
3302 Handle<FixedArray> jsfunction_result_caches( | 3324 Handle<FixedArray> jsfunction_result_caches( |
3303 isolate()->global_context()->jsfunction_result_caches()); | 3325 isolate()->global_context()->jsfunction_result_caches()); |
3304 if (jsfunction_result_caches->length() <= cache_id) { | 3326 if (jsfunction_result_caches->length() <= cache_id) { |
3305 __ Abort("Attempt to use undefined cache."); | 3327 __ Abort("Attempt to use undefined cache."); |
3306 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 3328 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3339 __ bind(¬_found); | 3361 __ bind(¬_found); |
3340 // Call runtime to perform the lookup. | 3362 // Call runtime to perform the lookup. |
3341 __ Push(cache, key); | 3363 __ Push(cache, key); |
3342 __ CallRuntime(Runtime::kGetFromCache, 2); | 3364 __ CallRuntime(Runtime::kGetFromCache, 2); |
3343 | 3365 |
3344 __ bind(&done); | 3366 __ bind(&done); |
3345 context()->Plug(v0); | 3367 context()->Plug(v0); |
3346 } | 3368 } |
3347 | 3369 |
3348 | 3370 |
3349 void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { | 3371 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) { |
| 3372 ZoneList<Expression*>* args = expr->arguments(); |
3350 ASSERT_EQ(2, args->length()); | 3373 ASSERT_EQ(2, args->length()); |
3351 | 3374 |
3352 Register right = v0; | 3375 Register right = v0; |
3353 Register left = a1; | 3376 Register left = a1; |
3354 Register tmp = a2; | 3377 Register tmp = a2; |
3355 Register tmp2 = a3; | 3378 Register tmp2 = a3; |
3356 | 3379 |
3357 VisitForStackValue(args->at(0)); | 3380 VisitForStackValue(args->at(0)); |
3358 VisitForAccumulatorValue(args->at(1)); // Result (right) in v0. | 3381 VisitForAccumulatorValue(args->at(1)); // Result (right) in v0. |
3359 __ pop(left); | 3382 __ pop(left); |
(...skipping 16 matching lines...) Expand all Loading... |
3376 __ LoadRoot(v0, Heap::kFalseValueRootIndex); | 3399 __ LoadRoot(v0, Heap::kFalseValueRootIndex); |
3377 __ jmp(&done); | 3400 __ jmp(&done); |
3378 __ bind(&ok); | 3401 __ bind(&ok); |
3379 __ LoadRoot(v0, Heap::kTrueValueRootIndex); | 3402 __ LoadRoot(v0, Heap::kTrueValueRootIndex); |
3380 __ bind(&done); | 3403 __ bind(&done); |
3381 | 3404 |
3382 context()->Plug(v0); | 3405 context()->Plug(v0); |
3383 } | 3406 } |
3384 | 3407 |
3385 | 3408 |
3386 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { | 3409 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
| 3410 ZoneList<Expression*>* args = expr->arguments(); |
3387 VisitForAccumulatorValue(args->at(0)); | 3411 VisitForAccumulatorValue(args->at(0)); |
3388 | 3412 |
3389 Label materialize_true, materialize_false; | 3413 Label materialize_true, materialize_false; |
3390 Label* if_true = NULL; | 3414 Label* if_true = NULL; |
3391 Label* if_false = NULL; | 3415 Label* if_false = NULL; |
3392 Label* fall_through = NULL; | 3416 Label* fall_through = NULL; |
3393 context()->PrepareTest(&materialize_true, &materialize_false, | 3417 context()->PrepareTest(&materialize_true, &materialize_false, |
3394 &if_true, &if_false, &fall_through); | 3418 &if_true, &if_false, &fall_through); |
3395 | 3419 |
3396 __ lw(a0, FieldMemOperand(v0, String::kHashFieldOffset)); | 3420 __ lw(a0, FieldMemOperand(v0, String::kHashFieldOffset)); |
3397 __ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask)); | 3421 __ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask)); |
3398 | 3422 |
3399 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 3423 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3400 Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through); | 3424 Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through); |
3401 | 3425 |
3402 context()->Plug(if_true, if_false); | 3426 context()->Plug(if_true, if_false); |
3403 } | 3427 } |
3404 | 3428 |
3405 | 3429 |
3406 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { | 3430 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { |
| 3431 ZoneList<Expression*>* args = expr->arguments(); |
3407 ASSERT(args->length() == 1); | 3432 ASSERT(args->length() == 1); |
3408 VisitForAccumulatorValue(args->at(0)); | 3433 VisitForAccumulatorValue(args->at(0)); |
3409 | 3434 |
3410 if (FLAG_debug_code) { | 3435 if (FLAG_debug_code) { |
3411 __ AbortIfNotString(v0); | 3436 __ AbortIfNotString(v0); |
3412 } | 3437 } |
3413 | 3438 |
3414 __ lw(v0, FieldMemOperand(v0, String::kHashFieldOffset)); | 3439 __ lw(v0, FieldMemOperand(v0, String::kHashFieldOffset)); |
3415 __ IndexFromHash(v0, v0); | 3440 __ IndexFromHash(v0, v0); |
3416 | 3441 |
3417 context()->Plug(v0); | 3442 context()->Plug(v0); |
3418 } | 3443 } |
3419 | 3444 |
3420 | 3445 |
3421 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { | 3446 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { |
3422 Label bailout, done, one_char_separator, long_separator, | 3447 Label bailout, done, one_char_separator, long_separator, |
3423 non_trivial_array, not_size_one_array, loop, | 3448 non_trivial_array, not_size_one_array, loop, |
3424 empty_separator_loop, one_char_separator_loop, | 3449 empty_separator_loop, one_char_separator_loop, |
3425 one_char_separator_loop_entry, long_separator_loop; | 3450 one_char_separator_loop_entry, long_separator_loop; |
3426 | 3451 ZoneList<Expression*>* args = expr->arguments(); |
3427 ASSERT(args->length() == 2); | 3452 ASSERT(args->length() == 2); |
3428 VisitForStackValue(args->at(1)); | 3453 VisitForStackValue(args->at(1)); |
3429 VisitForAccumulatorValue(args->at(0)); | 3454 VisitForAccumulatorValue(args->at(0)); |
3430 | 3455 |
3431 // All aliases of the same register have disjoint lifetimes. | 3456 // All aliases of the same register have disjoint lifetimes. |
3432 Register array = v0; | 3457 Register array = v0; |
3433 Register elements = no_reg; // Will be v0. | 3458 Register elements = no_reg; // Will be v0. |
3434 Register result = no_reg; // Will be v0. | 3459 Register result = no_reg; // Will be v0. |
3435 Register separator = a1; | 3460 Register separator = a1; |
3436 Register array_length = a2; | 3461 Register array_length = a2; |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3752 context()->Plug(Heap::kUndefinedValueRootIndex); | 3777 context()->Plug(Heap::kUndefinedValueRootIndex); |
3753 break; | 3778 break; |
3754 } | 3779 } |
3755 | 3780 |
3756 case Token::NOT: { | 3781 case Token::NOT: { |
3757 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); | 3782 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); |
3758 if (context()->IsEffect()) { | 3783 if (context()->IsEffect()) { |
3759 // Unary NOT has no side effects so it's only necessary to visit the | 3784 // Unary NOT has no side effects so it's only necessary to visit the |
3760 // subexpression. Match the optimizing compiler by not branching. | 3785 // subexpression. Match the optimizing compiler by not branching. |
3761 VisitForEffect(expr->expression()); | 3786 VisitForEffect(expr->expression()); |
| 3787 } else if (context()->IsTest()) { |
| 3788 const TestContext* test = TestContext::cast(context()); |
| 3789 // The labels are swapped for the recursive call. |
| 3790 VisitForControl(expr->expression(), |
| 3791 test->false_label(), |
| 3792 test->true_label(), |
| 3793 test->fall_through()); |
| 3794 context()->Plug(test->true_label(), test->false_label()); |
3762 } else { | 3795 } else { |
3763 Label materialize_true, materialize_false; | 3796 // We handle value contexts explicitly rather than simply visiting |
3764 Label* if_true = NULL; | 3797 // for control and plugging the control flow into the context, |
3765 Label* if_false = NULL; | 3798 // because we need to prepare a pair of extra administrative AST ids |
3766 Label* fall_through = NULL; | 3799 // for the optimizing compiler. |
3767 | 3800 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); |
3768 // Notice that the labels are swapped. | 3801 Label materialize_true, materialize_false, done; |
3769 context()->PrepareTest(&materialize_true, &materialize_false, | 3802 VisitForControl(expr->expression(), |
3770 &if_false, &if_true, &fall_through); | 3803 &materialize_false, |
3771 if (context()->IsTest()) ForwardBailoutToChild(expr); | 3804 &materialize_true, |
3772 VisitForControl(expr->expression(), if_true, if_false, fall_through); | 3805 &materialize_true); |
3773 context()->Plug(if_false, if_true); // Labels swapped. | 3806 __ bind(&materialize_true); |
| 3807 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); |
| 3808 __ LoadRoot(v0, Heap::kTrueValueRootIndex); |
| 3809 if (context()->IsStackValue()) __ push(v0); |
| 3810 __ jmp(&done); |
| 3811 __ bind(&materialize_false); |
| 3812 PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS); |
| 3813 __ LoadRoot(v0, Heap::kFalseValueRootIndex); |
| 3814 if (context()->IsStackValue()) __ push(v0); |
| 3815 __ bind(&done); |
3774 } | 3816 } |
3775 break; | 3817 break; |
3776 } | 3818 } |
3777 | 3819 |
3778 case Token::TYPEOF: { | 3820 case Token::TYPEOF: { |
3779 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); | 3821 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); |
3780 { StackValueContext context(this); | 3822 { StackValueContext context(this); |
3781 VisitForTypeofValue(expr->expression()); | 3823 VisitForTypeofValue(expr->expression()); |
3782 } | 3824 } |
3783 __ CallRuntime(Runtime::kTypeof, 1); | 3825 __ CallRuntime(Runtime::kTypeof, 1); |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4025 __ bind(&slow); | 4067 __ bind(&slow); |
4026 __ li(a0, Operand(proxy->name())); | 4068 __ li(a0, Operand(proxy->name())); |
4027 __ Push(cp, a0); | 4069 __ Push(cp, a0); |
4028 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 4070 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
4029 PrepareForBailout(expr, TOS_REG); | 4071 PrepareForBailout(expr, TOS_REG); |
4030 __ bind(&done); | 4072 __ bind(&done); |
4031 | 4073 |
4032 context()->Plug(v0); | 4074 context()->Plug(v0); |
4033 } else { | 4075 } else { |
4034 // This expression cannot throw a reference error at the top level. | 4076 // This expression cannot throw a reference error at the top level. |
4035 VisitInCurrentContext(expr); | 4077 VisitInDuplicateContext(expr); |
4036 } | 4078 } |
4037 } | 4079 } |
4038 | 4080 |
4039 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, | 4081 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, |
| 4082 Expression* sub_expr, |
4040 Handle<String> check) { | 4083 Handle<String> check) { |
4041 Label materialize_true, materialize_false; | 4084 Label materialize_true, materialize_false; |
4042 Label* if_true = NULL; | 4085 Label* if_true = NULL; |
4043 Label* if_false = NULL; | 4086 Label* if_false = NULL; |
4044 Label* fall_through = NULL; | 4087 Label* fall_through = NULL; |
4045 context()->PrepareTest(&materialize_true, &materialize_false, | 4088 context()->PrepareTest(&materialize_true, &materialize_false, |
4046 &if_true, &if_false, &fall_through); | 4089 &if_true, &if_false, &fall_through); |
4047 | 4090 |
4048 { AccumulatorValueContext context(this); | 4091 { AccumulatorValueContext context(this); |
4049 VisitForTypeofValue(expr); | 4092 VisitForTypeofValue(sub_expr); |
4050 } | 4093 } |
4051 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 4094 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4052 | 4095 |
4053 if (check->Equals(isolate()->heap()->number_symbol())) { | 4096 if (check->Equals(isolate()->heap()->number_symbol())) { |
4054 __ JumpIfSmi(v0, if_true); | 4097 __ JumpIfSmi(v0, if_true); |
4055 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); | 4098 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); |
4056 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4099 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
4057 Split(eq, v0, Operand(at), if_true, if_false, fall_through); | 4100 Split(eq, v0, Operand(at), if_true, if_false, fall_through); |
4058 } else if (check->Equals(isolate()->heap()->string_symbol())) { | 4101 } else if (check->Equals(isolate()->heap()->string_symbol())) { |
4059 __ JumpIfSmi(v0, if_false); | 4102 __ JumpIfSmi(v0, if_false); |
4060 // Check for undetectable objects => false. | 4103 // Check for undetectable objects => false. |
4061 __ GetObjectType(v0, v0, a1); | 4104 __ GetObjectType(v0, v0, a1); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4127 Label* fall_through = NULL; | 4170 Label* fall_through = NULL; |
4128 context()->PrepareTest(&materialize_true, &materialize_false, | 4171 context()->PrepareTest(&materialize_true, &materialize_false, |
4129 &if_true, &if_false, &fall_through); | 4172 &if_true, &if_false, &fall_through); |
4130 | 4173 |
4131 Token::Value op = expr->op(); | 4174 Token::Value op = expr->op(); |
4132 VisitForStackValue(expr->left()); | 4175 VisitForStackValue(expr->left()); |
4133 switch (op) { | 4176 switch (op) { |
4134 case Token::IN: | 4177 case Token::IN: |
4135 VisitForStackValue(expr->right()); | 4178 VisitForStackValue(expr->right()); |
4136 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 4179 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
4137 PrepareForBailoutBeforeSplit(false, NULL, NULL); | 4180 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
4138 __ LoadRoot(t0, Heap::kTrueValueRootIndex); | 4181 __ LoadRoot(t0, Heap::kTrueValueRootIndex); |
4139 Split(eq, v0, Operand(t0), if_true, if_false, fall_through); | 4182 Split(eq, v0, Operand(t0), if_true, if_false, fall_through); |
4140 break; | 4183 break; |
4141 | 4184 |
4142 case Token::INSTANCEOF: { | 4185 case Token::INSTANCEOF: { |
4143 VisitForStackValue(expr->right()); | 4186 VisitForStackValue(expr->right()); |
4144 InstanceofStub stub(InstanceofStub::kNoFlags); | 4187 InstanceofStub stub(InstanceofStub::kNoFlags); |
4145 __ CallStub(&stub); | 4188 __ CallStub(&stub); |
4146 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 4189 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4147 // The stub returns 0 for true. | 4190 // The stub returns 0 for true. |
4148 Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through); | 4191 Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through); |
4149 break; | 4192 break; |
4150 } | 4193 } |
4151 | 4194 |
4152 default: { | 4195 default: { |
4153 VisitForAccumulatorValue(expr->right()); | 4196 VisitForAccumulatorValue(expr->right()); |
4154 Condition cc = eq; | 4197 Condition cc = eq; |
4155 switch (op) { | 4198 switch (op) { |
4156 case Token::EQ_STRICT: | 4199 case Token::EQ_STRICT: |
(...skipping 27 matching lines...) Expand all Loading... |
4184 __ Or(a2, a0, Operand(a1)); | 4227 __ Or(a2, a0, Operand(a1)); |
4185 patch_site.EmitJumpIfNotSmi(a2, &slow_case); | 4228 patch_site.EmitJumpIfNotSmi(a2, &slow_case); |
4186 Split(cc, a1, Operand(a0), if_true, if_false, NULL); | 4229 Split(cc, a1, Operand(a0), if_true, if_false, NULL); |
4187 __ bind(&slow_case); | 4230 __ bind(&slow_case); |
4188 } | 4231 } |
4189 // Record position and call the compare IC. | 4232 // Record position and call the compare IC. |
4190 SetSourcePosition(expr->position()); | 4233 SetSourcePosition(expr->position()); |
4191 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4234 Handle<Code> ic = CompareIC::GetUninitialized(op); |
4192 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4235 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); |
4193 patch_site.EmitPatchInfo(); | 4236 patch_site.EmitPatchInfo(); |
4194 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 4237 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4195 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); | 4238 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); |
4196 } | 4239 } |
4197 } | 4240 } |
4198 | 4241 |
4199 // Convert the result of the comparison into one expected for this | 4242 // Convert the result of the comparison into one expected for this |
4200 // expression's context. | 4243 // expression's context. |
4201 context()->Plug(if_true, if_false); | 4244 context()->Plug(if_true, if_false); |
4202 } | 4245 } |
4203 | 4246 |
4204 | 4247 |
4205 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, | 4248 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, |
4206 Expression* sub_expr, | 4249 Expression* sub_expr, |
4207 NilValue nil) { | 4250 NilValue nil) { |
4208 Label materialize_true, materialize_false; | 4251 Label materialize_true, materialize_false; |
4209 Label* if_true = NULL; | 4252 Label* if_true = NULL; |
4210 Label* if_false = NULL; | 4253 Label* if_false = NULL; |
4211 Label* fall_through = NULL; | 4254 Label* fall_through = NULL; |
4212 context()->PrepareTest(&materialize_true, &materialize_false, | 4255 context()->PrepareTest(&materialize_true, &materialize_false, |
4213 &if_true, &if_false, &fall_through); | 4256 &if_true, &if_false, &fall_through); |
4214 | 4257 |
4215 VisitForAccumulatorValue(sub_expr); | 4258 VisitForAccumulatorValue(sub_expr); |
4216 PrepareForBailoutBeforeSplit(true, if_true, if_false); | 4259 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4217 Heap::RootListIndex nil_value = nil == kNullValue ? | 4260 Heap::RootListIndex nil_value = nil == kNullValue ? |
4218 Heap::kNullValueRootIndex : | 4261 Heap::kNullValueRootIndex : |
4219 Heap::kUndefinedValueRootIndex; | 4262 Heap::kUndefinedValueRootIndex; |
4220 __ mov(a0, result_register()); | 4263 __ mov(a0, result_register()); |
4221 __ LoadRoot(a1, nil_value); | 4264 __ LoadRoot(a1, nil_value); |
4222 if (expr->op() == Token::EQ_STRICT) { | 4265 if (expr->op() == Token::EQ_STRICT) { |
4223 Split(eq, a0, Operand(a1), if_true, if_false, fall_through); | 4266 Split(eq, a0, Operand(a1), if_true, if_false, fall_through); |
4224 } else { | 4267 } else { |
4225 Heap::RootListIndex other_nil_value = nil == kNullValue ? | 4268 Heap::RootListIndex other_nil_value = nil == kNullValue ? |
4226 Heap::kUndefinedValueRootIndex : | 4269 Heap::kUndefinedValueRootIndex : |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4343 *context_length = 0; | 4386 *context_length = 0; |
4344 return previous_; | 4387 return previous_; |
4345 } | 4388 } |
4346 | 4389 |
4347 | 4390 |
4348 #undef __ | 4391 #undef __ |
4349 | 4392 |
4350 } } // namespace v8::internal | 4393 } } // namespace v8::internal |
4351 | 4394 |
4352 #endif // V8_TARGET_ARCH_MIPS | 4395 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |