OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 break; | 239 break; |
240 case kStack: | 240 case kStack: |
241 __ push(reg); | 241 __ push(reg); |
242 break; | 242 break; |
243 } | 243 } |
244 break; | 244 break; |
245 | 245 |
246 case Expression::kTest: | 246 case Expression::kTest: |
247 // For simplicity we always test the accumulator register. | 247 // For simplicity we always test the accumulator register. |
248 if (!reg.is(result_register())) __ mov(result_register(), reg); | 248 if (!reg.is(result_register())) __ mov(result_register(), reg); |
249 DoTest(context); | 249 DoTest(true_label_, false_label_, NULL); |
250 break; | |
251 | |
252 case Expression::kValueTest: | |
253 case Expression::kTestValue: | |
254 if (!reg.is(result_register())) __ mov(result_register(), reg); | |
255 switch (location_) { | |
256 case kAccumulator: | |
257 break; | |
258 case kStack: | |
259 __ push(result_register()); | |
260 break; | |
261 } | |
262 DoTest(context); | |
263 break; | 250 break; |
264 } | 251 } |
265 } | 252 } |
266 | 253 |
267 | 254 |
268 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 255 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
269 switch (context) { | 256 switch (context) { |
270 case Expression::kUninitialized: | 257 case Expression::kUninitialized: |
271 UNREACHABLE(); | 258 UNREACHABLE(); |
272 case Expression::kEffect: | 259 case Expression::kEffect: |
273 // Nothing to do. | 260 // Nothing to do. |
274 break; | 261 break; |
275 case Expression::kValue: { | 262 case Expression::kValue: { |
276 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); | 263 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); |
277 switch (location_) { | 264 switch (location_) { |
278 case kAccumulator: | 265 case kAccumulator: |
279 __ mov(result_register(), slot_operand); | 266 __ mov(result_register(), slot_operand); |
280 break; | 267 break; |
281 case kStack: | 268 case kStack: |
282 // Memory operands can be pushed directly. | 269 // Memory operands can be pushed directly. |
283 __ push(slot_operand); | 270 __ push(slot_operand); |
284 break; | 271 break; |
285 } | 272 } |
286 break; | 273 break; |
287 } | 274 } |
288 | 275 |
289 case Expression::kTest: | 276 case Expression::kTest: |
290 // For simplicity we always test the accumulator register. | 277 // For simplicity we always test the accumulator register. |
291 Move(result_register(), slot); | 278 Move(result_register(), slot); |
292 DoTest(context); | 279 DoTest(true_label_, false_label_, NULL); |
293 break; | |
294 | |
295 case Expression::kValueTest: | |
296 case Expression::kTestValue: | |
297 Move(result_register(), slot); | |
298 switch (location_) { | |
299 case kAccumulator: | |
300 break; | |
301 case kStack: | |
302 __ push(result_register()); | |
303 break; | |
304 } | |
305 DoTest(context); | |
306 break; | 280 break; |
307 } | 281 } |
308 } | 282 } |
309 | 283 |
310 | 284 |
311 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 285 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
312 switch (context) { | 286 switch (context) { |
313 case Expression::kUninitialized: | 287 case Expression::kUninitialized: |
314 UNREACHABLE(); | 288 UNREACHABLE(); |
315 case Expression::kEffect: | 289 case Expression::kEffect: |
316 // Nothing to do. | 290 // Nothing to do. |
317 break; | 291 break; |
318 case Expression::kValue: | 292 case Expression::kValue: |
319 switch (location_) { | 293 switch (location_) { |
320 case kAccumulator: | 294 case kAccumulator: |
321 __ mov(result_register(), lit->handle()); | 295 __ mov(result_register(), lit->handle()); |
322 break; | 296 break; |
323 case kStack: | 297 case kStack: |
324 // Immediates can be pushed directly. | 298 // Immediates can be pushed directly. |
325 __ push(Immediate(lit->handle())); | 299 __ push(Immediate(lit->handle())); |
326 break; | 300 break; |
327 } | 301 } |
328 break; | 302 break; |
329 | 303 |
330 case Expression::kTest: | 304 case Expression::kTest: |
331 // For simplicity we always test the accumulator register. | 305 // For simplicity we always test the accumulator register. |
332 __ mov(result_register(), lit->handle()); | 306 __ mov(result_register(), lit->handle()); |
333 DoTest(context); | 307 DoTest(true_label_, false_label_, NULL); |
334 break; | |
335 | |
336 case Expression::kValueTest: | |
337 case Expression::kTestValue: | |
338 __ mov(result_register(), lit->handle()); | |
339 switch (location_) { | |
340 case kAccumulator: | |
341 break; | |
342 case kStack: | |
343 __ push(result_register()); | |
344 break; | |
345 } | |
346 DoTest(context); | |
347 break; | 308 break; |
348 } | 309 } |
349 } | 310 } |
350 | 311 |
351 | 312 |
352 void FullCodeGenerator::ApplyTOS(Expression::Context context) { | 313 void FullCodeGenerator::ApplyTOS(Expression::Context context) { |
353 switch (context) { | 314 switch (context) { |
354 case Expression::kUninitialized: | 315 case Expression::kUninitialized: |
355 UNREACHABLE(); | 316 UNREACHABLE(); |
356 | 317 |
357 case Expression::kEffect: | 318 case Expression::kEffect: |
358 __ Drop(1); | 319 __ Drop(1); |
359 break; | 320 break; |
360 | 321 |
361 case Expression::kValue: | 322 case Expression::kValue: |
362 switch (location_) { | 323 switch (location_) { |
363 case kAccumulator: | 324 case kAccumulator: |
364 __ pop(result_register()); | 325 __ pop(result_register()); |
365 break; | 326 break; |
366 case kStack: | 327 case kStack: |
367 break; | 328 break; |
368 } | 329 } |
369 break; | 330 break; |
370 | 331 |
371 case Expression::kTest: | 332 case Expression::kTest: |
372 // For simplicity we always test the accumulator register. | 333 // For simplicity we always test the accumulator register. |
373 __ pop(result_register()); | 334 __ pop(result_register()); |
374 DoTest(context); | 335 DoTest(true_label_, false_label_, NULL); |
375 break; | |
376 | |
377 case Expression::kValueTest: | |
378 case Expression::kTestValue: | |
379 switch (location_) { | |
380 case kAccumulator: | |
381 __ pop(result_register()); | |
382 break; | |
383 case kStack: | |
384 __ mov(result_register(), Operand(esp, 0)); | |
385 break; | |
386 } | |
387 DoTest(context); | |
388 break; | 336 break; |
389 } | 337 } |
390 } | 338 } |
391 | 339 |
392 | 340 |
393 void FullCodeGenerator::DropAndApply(int count, | 341 void FullCodeGenerator::DropAndApply(int count, |
394 Expression::Context context, | 342 Expression::Context context, |
395 Register reg) { | 343 Register reg) { |
396 ASSERT(count > 0); | 344 ASSERT(count > 0); |
397 ASSERT(!reg.is(esp)); | 345 ASSERT(!reg.is(esp)); |
(...skipping 15 matching lines...) Expand all Loading... |
413 if (count > 1) __ Drop(count - 1); | 361 if (count > 1) __ Drop(count - 1); |
414 __ mov(Operand(esp, 0), reg); | 362 __ mov(Operand(esp, 0), reg); |
415 break; | 363 break; |
416 } | 364 } |
417 break; | 365 break; |
418 | 366 |
419 case Expression::kTest: | 367 case Expression::kTest: |
420 // For simplicity we always test the accumulator register. | 368 // For simplicity we always test the accumulator register. |
421 __ Drop(count); | 369 __ Drop(count); |
422 if (!reg.is(result_register())) __ mov(result_register(), reg); | 370 if (!reg.is(result_register())) __ mov(result_register(), reg); |
423 DoTest(context); | 371 DoTest(true_label_, false_label_, NULL); |
424 break; | |
425 | |
426 case Expression::kValueTest: | |
427 case Expression::kTestValue: | |
428 switch (location_) { | |
429 case kAccumulator: | |
430 __ Drop(count); | |
431 if (!reg.is(result_register())) __ mov(result_register(), reg); | |
432 break; | |
433 case kStack: | |
434 if (count > 1) __ Drop(count - 1); | |
435 __ mov(result_register(), reg); | |
436 __ mov(Operand(esp, 0), result_register()); | |
437 break; | |
438 } | |
439 DoTest(context); | |
440 break; | 372 break; |
441 } | 373 } |
442 } | 374 } |
443 | 375 |
444 | 376 |
445 void FullCodeGenerator::PrepareTest(Label* materialize_true, | 377 void FullCodeGenerator::PrepareTest(Label* materialize_true, |
446 Label* materialize_false, | 378 Label* materialize_false, |
447 Label** if_true, | 379 Label** if_true, |
448 Label** if_false) { | 380 Label** if_false) { |
449 switch (context_) { | 381 switch (context_) { |
450 case Expression::kUninitialized: | 382 case Expression::kUninitialized: |
451 UNREACHABLE(); | 383 UNREACHABLE(); |
452 break; | 384 break; |
453 case Expression::kEffect: | 385 case Expression::kEffect: |
454 // In an effect context, the true and the false case branch to the | 386 // In an effect context, the true and the false case branch to the |
455 // same label. | 387 // same label. |
456 *if_true = *if_false = materialize_true; | 388 *if_true = *if_false = materialize_true; |
457 break; | 389 break; |
458 case Expression::kValue: | 390 case Expression::kValue: |
459 *if_true = materialize_true; | 391 *if_true = materialize_true; |
460 *if_false = materialize_false; | 392 *if_false = materialize_false; |
461 break; | 393 break; |
462 case Expression::kTest: | 394 case Expression::kTest: |
463 *if_true = true_label_; | 395 *if_true = true_label_; |
464 *if_false = false_label_; | 396 *if_false = false_label_; |
465 break; | 397 break; |
466 case Expression::kValueTest: | |
467 *if_true = materialize_true; | |
468 *if_false = false_label_; | |
469 break; | |
470 case Expression::kTestValue: | |
471 *if_true = true_label_; | |
472 *if_false = materialize_false; | |
473 break; | |
474 } | 398 } |
475 } | 399 } |
476 | 400 |
477 | 401 |
478 void FullCodeGenerator::Apply(Expression::Context context, | 402 void FullCodeGenerator::Apply(Expression::Context context, |
479 Label* materialize_true, | 403 Label* materialize_true, |
480 Label* materialize_false) { | 404 Label* materialize_false) { |
481 switch (context) { | 405 switch (context) { |
482 case Expression::kUninitialized: | 406 case Expression::kUninitialized: |
483 | 407 |
(...skipping 19 matching lines...) Expand all Loading... |
503 __ bind(materialize_false); | 427 __ bind(materialize_false); |
504 __ push(Immediate(Factory::false_value())); | 428 __ push(Immediate(Factory::false_value())); |
505 break; | 429 break; |
506 } | 430 } |
507 __ bind(&done); | 431 __ bind(&done); |
508 break; | 432 break; |
509 } | 433 } |
510 | 434 |
511 case Expression::kTest: | 435 case Expression::kTest: |
512 break; | 436 break; |
513 | |
514 case Expression::kValueTest: | |
515 __ bind(materialize_true); | |
516 switch (location_) { | |
517 case kAccumulator: | |
518 __ mov(result_register(), Factory::true_value()); | |
519 break; | |
520 case kStack: | |
521 __ push(Immediate(Factory::true_value())); | |
522 break; | |
523 } | |
524 __ jmp(true_label_); | |
525 break; | |
526 | |
527 case Expression::kTestValue: | |
528 __ bind(materialize_false); | |
529 switch (location_) { | |
530 case kAccumulator: | |
531 __ mov(result_register(), Factory::false_value()); | |
532 break; | |
533 case kStack: | |
534 __ push(Immediate(Factory::false_value())); | |
535 break; | |
536 } | |
537 __ jmp(false_label_); | |
538 break; | |
539 } | 437 } |
540 } | 438 } |
541 | 439 |
542 | 440 |
543 // Convert constant control flow (true or false) to the result expected for | 441 // Convert constant control flow (true or false) to the result expected for |
544 // a given expression context. | 442 // a given expression context. |
545 void FullCodeGenerator::Apply(Expression::Context context, bool flag) { | 443 void FullCodeGenerator::Apply(Expression::Context context, bool flag) { |
546 switch (context) { | 444 switch (context) { |
547 case Expression::kUninitialized: | 445 case Expression::kUninitialized: |
548 UNREACHABLE(); | 446 UNREACHABLE(); |
549 break; | 447 break; |
550 case Expression::kEffect: | 448 case Expression::kEffect: |
551 break; | 449 break; |
552 case Expression::kValue: { | 450 case Expression::kValue: { |
553 Handle<Object> value = | 451 Handle<Object> value = |
554 flag ? Factory::true_value() : Factory::false_value(); | 452 flag ? Factory::true_value() : Factory::false_value(); |
555 switch (location_) { | 453 switch (location_) { |
556 case kAccumulator: | 454 case kAccumulator: |
557 __ mov(result_register(), value); | 455 __ mov(result_register(), value); |
558 break; | 456 break; |
559 case kStack: | 457 case kStack: |
560 __ push(Immediate(value)); | 458 __ push(Immediate(value)); |
561 break; | 459 break; |
562 } | 460 } |
563 break; | 461 break; |
564 } | 462 } |
565 case Expression::kTest: | 463 case Expression::kTest: |
566 __ jmp(flag ? true_label_ : false_label_); | 464 __ jmp(flag ? true_label_ : false_label_); |
567 break; | 465 break; |
568 case Expression::kTestValue: | |
569 switch (location_) { | |
570 case kAccumulator: | |
571 // If value is false it's needed. | |
572 if (!flag) __ mov(result_register(), Factory::false_value()); | |
573 break; | |
574 case kStack: | |
575 // If value is false it's needed. | |
576 if (!flag) __ push(Immediate(Factory::false_value())); | |
577 break; | |
578 } | |
579 __ jmp(flag ? true_label_ : false_label_); | |
580 break; | |
581 case Expression::kValueTest: | |
582 switch (location_) { | |
583 case kAccumulator: | |
584 // If value is true it's needed. | |
585 if (flag) __ mov(result_register(), Factory::true_value()); | |
586 break; | |
587 case kStack: | |
588 // If value is true it's needed. | |
589 if (flag) __ push(Immediate(Factory::true_value())); | |
590 break; | |
591 } | |
592 __ jmp(flag ? true_label_ : false_label_); | |
593 break; | |
594 } | 466 } |
595 } | 467 } |
596 | 468 |
597 | 469 |
598 void FullCodeGenerator::DoTest(Expression::Context context) { | 470 void FullCodeGenerator::DoTest(Label* if_true, |
599 // The value to test is in the accumulator. If the value might be needed | 471 Label* if_false, |
600 // on the stack (value/test and test/value contexts with a stack location | 472 Label* fall_through) { |
601 // desired), then the value is already duplicated on the stack. | |
602 ASSERT_NE(NULL, true_label_); | |
603 ASSERT_NE(NULL, false_label_); | |
604 | |
605 // In value/test and test/value expression contexts with stack as the | |
606 // desired location, there is already an extra value on the stack. Use a | |
607 // label to discard it if unneeded. | |
608 Label discard; | |
609 Label* if_true = true_label_; | |
610 Label* if_false = false_label_; | |
611 switch (context) { | |
612 case Expression::kUninitialized: | |
613 case Expression::kEffect: | |
614 case Expression::kValue: | |
615 UNREACHABLE(); | |
616 case Expression::kTest: | |
617 break; | |
618 case Expression::kValueTest: | |
619 switch (location_) { | |
620 case kAccumulator: | |
621 break; | |
622 case kStack: | |
623 if_false = &discard; | |
624 break; | |
625 } | |
626 break; | |
627 case Expression::kTestValue: | |
628 switch (location_) { | |
629 case kAccumulator: | |
630 break; | |
631 case kStack: | |
632 if_true = &discard; | |
633 break; | |
634 } | |
635 break; | |
636 } | |
637 | |
638 // Emit the inlined tests assumed by the stub. | 473 // Emit the inlined tests assumed by the stub. |
639 __ cmp(result_register(), Factory::undefined_value()); | 474 __ cmp(result_register(), Factory::undefined_value()); |
640 __ j(equal, if_false); | 475 __ j(equal, if_false); |
641 __ cmp(result_register(), Factory::true_value()); | 476 __ cmp(result_register(), Factory::true_value()); |
642 __ j(equal, if_true); | 477 __ j(equal, if_true); |
643 __ cmp(result_register(), Factory::false_value()); | 478 __ cmp(result_register(), Factory::false_value()); |
644 __ j(equal, if_false); | 479 __ j(equal, if_false); |
645 ASSERT_EQ(0, kSmiTag); | 480 ASSERT_EQ(0, kSmiTag); |
646 __ test(result_register(), Operand(result_register())); | 481 __ test(result_register(), Operand(result_register())); |
647 __ j(zero, if_false); | 482 __ j(zero, if_false); |
648 __ test(result_register(), Immediate(kSmiTagMask)); | 483 __ test(result_register(), Immediate(kSmiTagMask)); |
649 __ j(zero, if_true); | 484 __ j(zero, if_true); |
650 | 485 |
651 // Save a copy of the value if it may be needed and isn't already saved. | |
652 switch (context) { | |
653 case Expression::kUninitialized: | |
654 case Expression::kEffect: | |
655 case Expression::kValue: | |
656 UNREACHABLE(); | |
657 case Expression::kTest: | |
658 break; | |
659 case Expression::kValueTest: | |
660 switch (location_) { | |
661 case kAccumulator: | |
662 __ push(result_register()); | |
663 break; | |
664 case kStack: | |
665 break; | |
666 } | |
667 break; | |
668 case Expression::kTestValue: | |
669 switch (location_) { | |
670 case kAccumulator: | |
671 __ push(result_register()); | |
672 break; | |
673 case kStack: | |
674 break; | |
675 } | |
676 break; | |
677 } | |
678 | |
679 // Call the ToBoolean stub for all other cases. | 486 // Call the ToBoolean stub for all other cases. |
680 ToBooleanStub stub; | 487 ToBooleanStub stub; |
681 __ push(result_register()); | 488 __ push(result_register()); |
682 __ CallStub(&stub); | 489 __ CallStub(&stub); |
683 __ test(eax, Operand(eax)); | 490 __ test(eax, Operand(eax)); |
684 | 491 |
685 // The stub returns nonzero for true. Complete based on the context. | 492 // The stub returns nonzero for true. |
686 switch (context) { | 493 Split(not_zero, if_true, if_false, fall_through); |
687 case Expression::kUninitialized: | 494 } |
688 case Expression::kEffect: | |
689 case Expression::kValue: | |
690 UNREACHABLE(); | |
691 | 495 |
692 case Expression::kTest: | |
693 __ j(not_zero, true_label_); | |
694 __ jmp(false_label_); | |
695 break; | |
696 | 496 |
697 case Expression::kValueTest: | 497 void FullCodeGenerator::Split(Condition cc, |
698 switch (location_) { | 498 Label* if_true, |
699 case kAccumulator: | 499 Label* if_false, |
700 __ j(zero, &discard); | 500 Label* fall_through) { |
701 __ pop(result_register()); | 501 if (if_false == fall_through) { |
702 __ jmp(true_label_); | 502 __ j(cc, if_true); |
703 break; | 503 } else if (if_true == fall_through) { |
704 case kStack: | 504 __ j(NegateCondition(cc), if_false); |
705 __ j(not_zero, true_label_); | 505 } else { |
706 break; | 506 __ j(cc, if_true); |
707 } | 507 __ jmp(if_false); |
708 __ bind(&discard); | |
709 __ Drop(1); | |
710 __ jmp(false_label_); | |
711 break; | |
712 | |
713 case Expression::kTestValue: | |
714 switch (location_) { | |
715 case kAccumulator: | |
716 __ j(not_zero, &discard); | |
717 __ pop(result_register()); | |
718 __ jmp(false_label_); | |
719 break; | |
720 case kStack: | |
721 __ j(zero, false_label_); | |
722 break; | |
723 } | |
724 __ bind(&discard); | |
725 __ Drop(1); | |
726 __ jmp(true_label_); | |
727 break; | |
728 } | 508 } |
729 } | 509 } |
730 | 510 |
731 | 511 |
732 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 512 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
733 switch (slot->type()) { | 513 switch (slot->type()) { |
734 case Slot::PARAMETER: | 514 case Slot::PARAMETER: |
735 case Slot::LOCAL: | 515 case Slot::LOCAL: |
736 return Operand(ebp, SlotOffset(slot)); | 516 return Operand(ebp, SlotOffset(slot)); |
737 case Slot::CONTEXT: { | 517 case Slot::CONTEXT: { |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 Comment cmnt(masm_, "[ RegExpLiteral"); | 976 Comment cmnt(masm_, "[ RegExpLiteral"); |
1197 Label materialized; | 977 Label materialized; |
1198 // Registers will be used as follows: | 978 // Registers will be used as follows: |
1199 // edi = JS function. | 979 // edi = JS function. |
1200 // ecx = literals array. | 980 // ecx = literals array. |
1201 // ebx = regexp literal. | 981 // ebx = regexp literal. |
1202 // eax = regexp literal clone. | 982 // eax = regexp literal clone. |
1203 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 983 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1204 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 984 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
1205 int literal_offset = | 985 int literal_offset = |
1206 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 986 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
1207 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 987 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
1208 __ cmp(ebx, Factory::undefined_value()); | 988 __ cmp(ebx, Factory::undefined_value()); |
1209 __ j(not_equal, &materialized); | 989 __ j(not_equal, &materialized); |
1210 | 990 |
1211 // Create regexp literal using runtime function | 991 // Create regexp literal using runtime function |
1212 // Result will be in eax. | 992 // Result will be in eax. |
1213 __ push(ecx); | 993 __ push(ecx); |
1214 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 994 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
1215 __ push(Immediate(expr->pattern())); | 995 __ push(Immediate(expr->pattern())); |
1216 __ push(Immediate(expr->flags())); | 996 __ push(Immediate(expr->flags())); |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1954 ASSERT(args->length() == 1); | 1734 ASSERT(args->length() == 1); |
1955 | 1735 |
1956 VisitForValue(args->at(0), kAccumulator); | 1736 VisitForValue(args->at(0), kAccumulator); |
1957 | 1737 |
1958 Label materialize_true, materialize_false; | 1738 Label materialize_true, materialize_false; |
1959 Label* if_true = NULL; | 1739 Label* if_true = NULL; |
1960 Label* if_false = NULL; | 1740 Label* if_false = NULL; |
1961 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1741 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1962 | 1742 |
1963 __ test(eax, Immediate(kSmiTagMask)); | 1743 __ test(eax, Immediate(kSmiTagMask)); |
1964 __ j(zero, if_true); | 1744 Split(zero, if_true, if_false, NULL); |
1965 __ jmp(if_false); | |
1966 | 1745 |
1967 Apply(context_, if_true, if_false); | 1746 Apply(context_, if_true, if_false); |
1968 } | 1747 } |
1969 | 1748 |
1970 | 1749 |
1971 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { | 1750 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { |
1972 ASSERT(args->length() == 1); | 1751 ASSERT(args->length() == 1); |
1973 | 1752 |
1974 VisitForValue(args->at(0), kAccumulator); | 1753 VisitForValue(args->at(0), kAccumulator); |
1975 | 1754 |
1976 Label materialize_true, materialize_false; | 1755 Label materialize_true, materialize_false; |
1977 Label* if_true = NULL; | 1756 Label* if_true = NULL; |
1978 Label* if_false = NULL; | 1757 Label* if_false = NULL; |
1979 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1758 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1980 | 1759 |
1981 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); | 1760 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); |
1982 __ j(zero, if_true); | 1761 Split(zero, if_true, if_false, NULL); |
1983 __ jmp(if_false); | |
1984 | 1762 |
1985 Apply(context_, if_true, if_false); | 1763 Apply(context_, if_true, if_false); |
1986 } | 1764 } |
1987 | 1765 |
1988 | 1766 |
1989 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { | 1767 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { |
1990 ASSERT(args->length() == 1); | 1768 ASSERT(args->length() == 1); |
1991 | 1769 |
1992 VisitForValue(args->at(0), kAccumulator); | 1770 VisitForValue(args->at(0), kAccumulator); |
1993 | 1771 |
1994 Label materialize_true, materialize_false; | 1772 Label materialize_true, materialize_false; |
1995 Label* if_true = NULL; | 1773 Label* if_true = NULL; |
1996 Label* if_false = NULL; | 1774 Label* if_false = NULL; |
1997 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1775 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1998 | 1776 |
1999 __ test(eax, Immediate(kSmiTagMask)); | 1777 __ test(eax, Immediate(kSmiTagMask)); |
2000 __ j(zero, if_false); | 1778 __ j(zero, if_false); |
2001 __ cmp(eax, Factory::null_value()); | 1779 __ cmp(eax, Factory::null_value()); |
2002 __ j(equal, if_true); | 1780 __ j(equal, if_true); |
2003 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 1781 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2004 // Undetectable objects behave like undefined when tested with typeof. | 1782 // Undetectable objects behave like undefined when tested with typeof. |
2005 __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); | 1783 __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); |
2006 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); | 1784 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); |
2007 __ j(not_zero, if_false); | 1785 __ j(not_zero, if_false); |
2008 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 1786 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
2009 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 1787 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); |
2010 __ j(below, if_false); | 1788 __ j(below, if_false); |
2011 __ cmp(ecx, LAST_JS_OBJECT_TYPE); | 1789 __ cmp(ecx, LAST_JS_OBJECT_TYPE); |
2012 __ j(below_equal, if_true); | 1790 Split(below_equal, if_true, if_false, NULL); |
2013 __ jmp(if_false); | |
2014 | 1791 |
2015 Apply(context_, if_true, if_false); | 1792 Apply(context_, if_true, if_false); |
2016 } | 1793 } |
2017 | 1794 |
2018 | 1795 |
2019 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { | 1796 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { |
2020 ASSERT(args->length() == 1); | 1797 ASSERT(args->length() == 1); |
2021 | 1798 |
2022 VisitForValue(args->at(0), kAccumulator); | 1799 VisitForValue(args->at(0), kAccumulator); |
2023 | 1800 |
2024 Label materialize_true, materialize_false; | 1801 Label materialize_true, materialize_false; |
2025 Label* if_true = NULL; | 1802 Label* if_true = NULL; |
2026 Label* if_false = NULL; | 1803 Label* if_false = NULL; |
2027 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1804 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2028 | 1805 |
2029 __ test(eax, Immediate(kSmiTagMask)); | 1806 __ test(eax, Immediate(kSmiTagMask)); |
2030 __ j(equal, if_false); | 1807 __ j(equal, if_false); |
2031 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx); | 1808 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx); |
2032 __ j(above_equal, if_true); | 1809 Split(above_equal, if_true, if_false, NULL); |
2033 __ jmp(if_false); | |
2034 | 1810 |
2035 Apply(context_, if_true, if_false); | 1811 Apply(context_, if_true, if_false); |
2036 } | 1812 } |
2037 | 1813 |
2038 | 1814 |
2039 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 1815 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
2040 ASSERT(args->length() == 1); | 1816 ASSERT(args->length() == 1); |
2041 | 1817 |
2042 VisitForValue(args->at(0), kAccumulator); | 1818 VisitForValue(args->at(0), kAccumulator); |
2043 | 1819 |
2044 Label materialize_true, materialize_false; | 1820 Label materialize_true, materialize_false; |
2045 Label* if_true = NULL; | 1821 Label* if_true = NULL; |
2046 Label* if_false = NULL; | 1822 Label* if_false = NULL; |
2047 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1823 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2048 | 1824 |
2049 __ test(eax, Immediate(kSmiTagMask)); | 1825 __ test(eax, Immediate(kSmiTagMask)); |
2050 __ j(zero, if_false); | 1826 __ j(zero, if_false); |
2051 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 1827 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2052 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); | 1828 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); |
2053 __ test(ebx, Immediate(1 << Map::kIsUndetectable)); | 1829 __ test(ebx, Immediate(1 << Map::kIsUndetectable)); |
2054 __ j(not_zero, if_true); | 1830 Split(not_zero, if_true, if_false, NULL); |
2055 __ jmp(if_false); | |
2056 | 1831 |
2057 Apply(context_, if_true, if_false); | 1832 Apply(context_, if_true, if_false); |
2058 } | 1833 } |
2059 | 1834 |
2060 | 1835 |
2061 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 1836 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
2062 ZoneList<Expression*>* args) { | 1837 ZoneList<Expression*>* args) { |
2063 ASSERT(args->length() == 1); | 1838 ASSERT(args->length() == 1); |
2064 | 1839 |
2065 VisitForValue(args->at(0), kAccumulator); | 1840 VisitForValue(args->at(0), kAccumulator); |
(...skipping 17 matching lines...) Expand all Loading... |
2083 VisitForValue(args->at(0), kAccumulator); | 1858 VisitForValue(args->at(0), kAccumulator); |
2084 | 1859 |
2085 Label materialize_true, materialize_false; | 1860 Label materialize_true, materialize_false; |
2086 Label* if_true = NULL; | 1861 Label* if_true = NULL; |
2087 Label* if_false = NULL; | 1862 Label* if_false = NULL; |
2088 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1863 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2089 | 1864 |
2090 __ test(eax, Immediate(kSmiTagMask)); | 1865 __ test(eax, Immediate(kSmiTagMask)); |
2091 __ j(zero, if_false); | 1866 __ j(zero, if_false); |
2092 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 1867 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
2093 __ j(equal, if_true); | 1868 Split(equal, if_true, if_false, NULL); |
2094 __ jmp(if_false); | |
2095 | 1869 |
2096 Apply(context_, if_true, if_false); | 1870 Apply(context_, if_true, if_false); |
2097 } | 1871 } |
2098 | 1872 |
2099 | 1873 |
2100 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { | 1874 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { |
2101 ASSERT(args->length() == 1); | 1875 ASSERT(args->length() == 1); |
2102 | 1876 |
2103 VisitForValue(args->at(0), kAccumulator); | 1877 VisitForValue(args->at(0), kAccumulator); |
2104 | 1878 |
2105 Label materialize_true, materialize_false; | 1879 Label materialize_true, materialize_false; |
2106 Label* if_true = NULL; | 1880 Label* if_true = NULL; |
2107 Label* if_false = NULL; | 1881 Label* if_false = NULL; |
2108 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1882 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2109 | 1883 |
2110 __ test(eax, Immediate(kSmiTagMask)); | 1884 __ test(eax, Immediate(kSmiTagMask)); |
2111 __ j(equal, if_false); | 1885 __ j(equal, if_false); |
2112 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); | 1886 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); |
2113 __ j(equal, if_true); | 1887 Split(equal, if_true, if_false, NULL); |
2114 __ jmp(if_false); | |
2115 | 1888 |
2116 Apply(context_, if_true, if_false); | 1889 Apply(context_, if_true, if_false); |
2117 } | 1890 } |
2118 | 1891 |
2119 | 1892 |
2120 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { | 1893 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { |
2121 ASSERT(args->length() == 1); | 1894 ASSERT(args->length() == 1); |
2122 | 1895 |
2123 VisitForValue(args->at(0), kAccumulator); | 1896 VisitForValue(args->at(0), kAccumulator); |
2124 | 1897 |
2125 Label materialize_true, materialize_false; | 1898 Label materialize_true, materialize_false; |
2126 Label* if_true = NULL; | 1899 Label* if_true = NULL; |
2127 Label* if_false = NULL; | 1900 Label* if_false = NULL; |
2128 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1901 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2129 | 1902 |
2130 __ test(eax, Immediate(kSmiTagMask)); | 1903 __ test(eax, Immediate(kSmiTagMask)); |
2131 __ j(equal, if_false); | 1904 __ j(equal, if_false); |
2132 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); | 1905 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); |
2133 __ j(equal, if_true); | 1906 Split(equal, if_true, if_false, NULL); |
2134 __ jmp(if_false); | |
2135 | 1907 |
2136 Apply(context_, if_true, if_false); | 1908 Apply(context_, if_true, if_false); |
2137 } | 1909 } |
2138 | 1910 |
2139 | 1911 |
2140 | 1912 |
2141 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { | 1913 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { |
2142 ASSERT(args->length() == 0); | 1914 ASSERT(args->length() == 0); |
2143 | 1915 |
2144 Label materialize_true, materialize_false; | 1916 Label materialize_true, materialize_false; |
2145 Label* if_true = NULL; | 1917 Label* if_true = NULL; |
2146 Label* if_false = NULL; | 1918 Label* if_false = NULL; |
2147 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1919 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2148 | 1920 |
2149 // Get the frame pointer for the calling frame. | 1921 // Get the frame pointer for the calling frame. |
2150 __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 1922 __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
2151 | 1923 |
2152 // Skip the arguments adaptor frame if it exists. | 1924 // Skip the arguments adaptor frame if it exists. |
2153 Label check_frame_marker; | 1925 Label check_frame_marker; |
2154 __ cmp(Operand(eax, StandardFrameConstants::kContextOffset), | 1926 __ cmp(Operand(eax, StandardFrameConstants::kContextOffset), |
2155 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1927 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
2156 __ j(not_equal, &check_frame_marker); | 1928 __ j(not_equal, &check_frame_marker); |
2157 __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset)); | 1929 __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset)); |
2158 | 1930 |
2159 // Check the marker in the calling frame. | 1931 // Check the marker in the calling frame. |
2160 __ bind(&check_frame_marker); | 1932 __ bind(&check_frame_marker); |
2161 __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset), | 1933 __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset), |
2162 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); | 1934 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); |
2163 __ j(equal, if_true); | 1935 Split(equal, if_true, if_false, NULL); |
2164 __ jmp(if_false); | |
2165 | 1936 |
2166 Apply(context_, if_true, if_false); | 1937 Apply(context_, if_true, if_false); |
2167 } | 1938 } |
2168 | 1939 |
2169 | 1940 |
2170 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { | 1941 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { |
2171 ASSERT(args->length() == 2); | 1942 ASSERT(args->length() == 2); |
2172 | 1943 |
2173 // Load the two objects into registers and perform the comparison. | 1944 // Load the two objects into registers and perform the comparison. |
2174 VisitForValue(args->at(0), kStack); | 1945 VisitForValue(args->at(0), kStack); |
2175 VisitForValue(args->at(1), kAccumulator); | 1946 VisitForValue(args->at(1), kAccumulator); |
2176 | 1947 |
2177 Label materialize_true, materialize_false; | 1948 Label materialize_true, materialize_false; |
2178 Label* if_true = NULL; | 1949 Label* if_true = NULL; |
2179 Label* if_false = NULL; | 1950 Label* if_false = NULL; |
2180 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1951 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2181 | 1952 |
2182 __ pop(ebx); | 1953 __ pop(ebx); |
2183 __ cmp(eax, Operand(ebx)); | 1954 __ cmp(eax, Operand(ebx)); |
2184 __ j(equal, if_true); | 1955 Split(equal, if_true, if_false, NULL); |
2185 __ jmp(if_false); | |
2186 | 1956 |
2187 Apply(context_, if_true, if_false); | 1957 Apply(context_, if_true, if_false); |
2188 } | 1958 } |
2189 | 1959 |
2190 | 1960 |
2191 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 1961 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
2192 ASSERT(args->length() == 1); | 1962 ASSERT(args->length() == 1); |
2193 | 1963 |
2194 // ArgumentsAccessStub expects the key in edx and the formal | 1964 // ArgumentsAccessStub expects the key in edx and the formal |
2195 // parameter count in eax. | 1965 // parameter count in eax. |
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2838 case Expression::kValue: | 2608 case Expression::kValue: |
2839 switch (location_) { | 2609 switch (location_) { |
2840 case kAccumulator: | 2610 case kAccumulator: |
2841 __ mov(result_register(), Factory::undefined_value()); | 2611 __ mov(result_register(), Factory::undefined_value()); |
2842 break; | 2612 break; |
2843 case kStack: | 2613 case kStack: |
2844 __ push(Immediate(Factory::undefined_value())); | 2614 __ push(Immediate(Factory::undefined_value())); |
2845 break; | 2615 break; |
2846 } | 2616 } |
2847 break; | 2617 break; |
2848 case Expression::kTestValue: | |
2849 // Value is false so it's needed. | |
2850 switch (location_) { | |
2851 case kAccumulator: | |
2852 __ mov(result_register(), Factory::undefined_value()); | |
2853 break; | |
2854 case kStack: | |
2855 __ push(Immediate(Factory::undefined_value())); | |
2856 break; | |
2857 } | |
2858 // Fall through. | |
2859 case Expression::kTest: | 2618 case Expression::kTest: |
2860 case Expression::kValueTest: | |
2861 __ jmp(false_label_); | 2619 __ jmp(false_label_); |
2862 break; | 2620 break; |
2863 } | 2621 } |
2864 break; | 2622 break; |
2865 } | 2623 } |
2866 | 2624 |
2867 case Token::NOT: { | 2625 case Token::NOT: { |
2868 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); | 2626 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); |
2869 Label materialize_true, materialize_false; | 2627 Label materialize_true, materialize_false; |
2870 Label* if_true = NULL; | 2628 Label* if_true = NULL; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3031 // Save result for postfix expressions. | 2789 // Save result for postfix expressions. |
3032 if (expr->is_postfix()) { | 2790 if (expr->is_postfix()) { |
3033 switch (context_) { | 2791 switch (context_) { |
3034 case Expression::kUninitialized: | 2792 case Expression::kUninitialized: |
3035 UNREACHABLE(); | 2793 UNREACHABLE(); |
3036 case Expression::kEffect: | 2794 case Expression::kEffect: |
3037 // Do not save result. | 2795 // Do not save result. |
3038 break; | 2796 break; |
3039 case Expression::kValue: | 2797 case Expression::kValue: |
3040 case Expression::kTest: | 2798 case Expression::kTest: |
3041 case Expression::kValueTest: | |
3042 case Expression::kTestValue: | |
3043 // Save the result on the stack. If we have a named or keyed property | 2799 // Save the result on the stack. If we have a named or keyed property |
3044 // we store the result under the receiver that is currently on top | 2800 // we store the result under the receiver that is currently on top |
3045 // of the stack. | 2801 // of the stack. |
3046 switch (assign_type) { | 2802 switch (assign_type) { |
3047 case VARIABLE: | 2803 case VARIABLE: |
3048 __ push(eax); | 2804 __ push(eax); |
3049 break; | 2805 break; |
3050 case NAMED_PROPERTY: | 2806 case NAMED_PROPERTY: |
3051 __ mov(Operand(esp, kPointerSize), eax); | 2807 __ mov(Operand(esp, kPointerSize), eax); |
3052 break; | 2808 break; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3139 } | 2895 } |
3140 } else { | 2896 } else { |
3141 Apply(context_, eax); | 2897 Apply(context_, eax); |
3142 } | 2898 } |
3143 break; | 2899 break; |
3144 } | 2900 } |
3145 } | 2901 } |
3146 } | 2902 } |
3147 | 2903 |
3148 | 2904 |
3149 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | |
3150 Comment cmnt(masm_, "[ BinaryOperation"); | |
3151 switch (expr->op()) { | |
3152 case Token::COMMA: | |
3153 VisitForEffect(expr->left()); | |
3154 Visit(expr->right()); | |
3155 break; | |
3156 | |
3157 case Token::OR: | |
3158 case Token::AND: | |
3159 EmitLogicalOperation(expr); | |
3160 break; | |
3161 | |
3162 case Token::ADD: | |
3163 case Token::SUB: | |
3164 case Token::DIV: | |
3165 case Token::MOD: | |
3166 case Token::MUL: | |
3167 case Token::BIT_OR: | |
3168 case Token::BIT_AND: | |
3169 case Token::BIT_XOR: | |
3170 case Token::SHL: | |
3171 case Token::SHR: | |
3172 case Token::SAR: | |
3173 VisitForValue(expr->left(), kStack); | |
3174 VisitForValue(expr->right(), kAccumulator); | |
3175 EmitBinaryOp(expr->op(), context_); | |
3176 break; | |
3177 | |
3178 default: | |
3179 UNREACHABLE(); | |
3180 } | |
3181 } | |
3182 | |
3183 | |
3184 void FullCodeGenerator::EmitNullCompare(bool strict, | 2905 void FullCodeGenerator::EmitNullCompare(bool strict, |
3185 Register obj, | 2906 Register obj, |
3186 Register null_const, | 2907 Register null_const, |
3187 Label* if_true, | 2908 Label* if_true, |
3188 Label* if_false, | 2909 Label* if_false, |
3189 Register scratch) { | 2910 Register scratch) { |
3190 __ cmp(obj, Operand(null_const)); | 2911 __ cmp(obj, Operand(null_const)); |
3191 if (strict) { | 2912 if (strict) { |
3192 __ j(equal, if_true); | 2913 Split(equal, if_true, if_false, NULL); |
3193 } else { | 2914 } else { |
3194 __ j(equal, if_true); | 2915 __ j(equal, if_true); |
3195 __ cmp(obj, Factory::undefined_value()); | 2916 __ cmp(obj, Factory::undefined_value()); |
3196 __ j(equal, if_true); | 2917 __ j(equal, if_true); |
3197 __ test(obj, Immediate(kSmiTagMask)); | 2918 __ test(obj, Immediate(kSmiTagMask)); |
3198 __ j(zero, if_false); | 2919 __ j(zero, if_false); |
3199 // It can be an undetectable object. | 2920 // It can be an undetectable object. |
3200 __ mov(scratch, FieldOperand(obj, HeapObject::kMapOffset)); | 2921 __ mov(scratch, FieldOperand(obj, HeapObject::kMapOffset)); |
3201 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 2922 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
3202 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 2923 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
3203 __ j(not_zero, if_true); | 2924 Split(not_zero, if_true, if_false, NULL); |
3204 } | 2925 } |
3205 __ jmp(if_false); | |
3206 } | 2926 } |
3207 | 2927 |
3208 | 2928 |
3209 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 2929 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
3210 Comment cmnt(masm_, "[ CompareOperation"); | 2930 Comment cmnt(masm_, "[ CompareOperation"); |
3211 | 2931 |
3212 // Always perform the comparison for its control flow. Pack the result | 2932 // Always perform the comparison for its control flow. Pack the result |
3213 // into the expression's context after the comparison is performed. | 2933 // into the expression's context after the comparison is performed. |
3214 | 2934 |
3215 Label materialize_true, materialize_false; | 2935 Label materialize_true, materialize_false; |
3216 Label* if_true = NULL; | 2936 Label* if_true = NULL; |
3217 Label* if_false = NULL; | 2937 Label* if_false = NULL; |
3218 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 2938 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
3219 | 2939 |
3220 VisitForValue(expr->left(), kStack); | 2940 VisitForValue(expr->left(), kStack); |
3221 switch (expr->op()) { | 2941 switch (expr->op()) { |
3222 case Token::IN: | 2942 case Token::IN: |
3223 VisitForValue(expr->right(), kStack); | 2943 VisitForValue(expr->right(), kStack); |
3224 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 2944 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
3225 __ cmp(eax, Factory::true_value()); | 2945 __ cmp(eax, Factory::true_value()); |
3226 __ j(equal, if_true); | 2946 Split(equal, if_true, if_false, NULL); |
3227 __ jmp(if_false); | |
3228 break; | 2947 break; |
3229 | 2948 |
3230 case Token::INSTANCEOF: { | 2949 case Token::INSTANCEOF: { |
3231 VisitForValue(expr->right(), kStack); | 2950 VisitForValue(expr->right(), kStack); |
3232 InstanceofStub stub; | 2951 InstanceofStub stub; |
3233 __ CallStub(&stub); | 2952 __ CallStub(&stub); |
3234 __ test(eax, Operand(eax)); | 2953 __ test(eax, Operand(eax)); |
3235 __ j(zero, if_true); // The stub returns 0 for true. | 2954 // The stub returns 0 for true. |
3236 __ jmp(if_false); | 2955 Split(zero, if_true, if_false, NULL); |
3237 break; | 2956 break; |
3238 } | 2957 } |
3239 | 2958 |
3240 default: { | 2959 default: { |
3241 VisitForValue(expr->right(), kAccumulator); | 2960 VisitForValue(expr->right(), kAccumulator); |
3242 Condition cc = no_condition; | 2961 Condition cc = no_condition; |
3243 bool strict = false; | 2962 bool strict = false; |
3244 switch (expr->op()) { | 2963 switch (expr->op()) { |
3245 case Token::EQ_STRICT: | 2964 case Token::EQ_STRICT: |
3246 strict = true; | 2965 strict = true; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3297 __ test(ecx, Immediate(kSmiTagMask)); | 3016 __ test(ecx, Immediate(kSmiTagMask)); |
3298 __ j(not_zero, &slow_case, not_taken); | 3017 __ j(not_zero, &slow_case, not_taken); |
3299 __ cmp(edx, Operand(eax)); | 3018 __ cmp(edx, Operand(eax)); |
3300 __ j(cc, if_true); | 3019 __ j(cc, if_true); |
3301 __ jmp(if_false); | 3020 __ jmp(if_false); |
3302 | 3021 |
3303 __ bind(&slow_case); | 3022 __ bind(&slow_case); |
3304 CompareStub stub(cc, strict); | 3023 CompareStub stub(cc, strict); |
3305 __ CallStub(&stub); | 3024 __ CallStub(&stub); |
3306 __ test(eax, Operand(eax)); | 3025 __ test(eax, Operand(eax)); |
3307 __ j(cc, if_true); | 3026 Split(cc, if_true, if_false, NULL); |
3308 __ jmp(if_false); | |
3309 } | 3027 } |
3310 } | 3028 } |
3311 | 3029 |
3312 // Convert the result of the comparison into one expected for this | 3030 // Convert the result of the comparison into one expected for this |
3313 // expression's context. | 3031 // expression's context. |
3314 Apply(context_, if_true, if_false); | 3032 Apply(context_, if_true, if_false); |
3315 } | 3033 } |
3316 | 3034 |
3317 | 3035 |
3318 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 3036 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3367 // And return. | 3085 // And return. |
3368 __ ret(0); | 3086 __ ret(0); |
3369 } | 3087 } |
3370 | 3088 |
3371 | 3089 |
3372 #undef __ | 3090 #undef __ |
3373 | 3091 |
3374 } } // namespace v8::internal | 3092 } } // namespace v8::internal |
3375 | 3093 |
3376 #endif // V8_TARGET_ARCH_IA32 | 3094 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |