OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 switch (location_) { | 259 switch (location_) { |
260 case kAccumulator: | 260 case kAccumulator: |
261 if (!reg.is(result_register())) __ mov(result_register(), reg); | 261 if (!reg.is(result_register())) __ mov(result_register(), reg); |
262 break; | 262 break; |
263 case kStack: | 263 case kStack: |
264 __ push(reg); | 264 __ push(reg); |
265 break; | 265 break; |
266 } | 266 } |
267 break; | 267 break; |
268 | 268 |
269 case Expression::kValueTest: | |
270 case Expression::kTestValue: | |
271 // Push an extra copy of the value in case it's needed. | |
272 __ push(reg); | |
273 // Fall through. | |
274 | |
275 case Expression::kTest: | 269 case Expression::kTest: |
276 // We always call the runtime on ARM, so push the value as argument. | 270 // For simplicity we always test the accumulator register. |
277 __ push(reg); | 271 if (!reg.is(result_register())) __ mov(result_register(), reg); |
278 DoTest(context); | 272 DoTest(true_label_, false_label_, NULL); |
279 break; | 273 break; |
280 } | 274 } |
281 } | 275 } |
282 | 276 |
283 | 277 |
284 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 278 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
285 switch (context) { | 279 switch (context) { |
286 case Expression::kUninitialized: | 280 case Expression::kUninitialized: |
287 UNREACHABLE(); | 281 UNREACHABLE(); |
288 case Expression::kEffect: | 282 case Expression::kEffect: |
289 // Nothing to do. | 283 // Nothing to do. |
290 break; | 284 break; |
291 case Expression::kValue: | 285 case Expression::kValue: |
292 case Expression::kTest: | 286 case Expression::kTest: |
293 case Expression::kValueTest: | |
294 case Expression::kTestValue: | |
295 // On ARM we have to move the value into a register to do anything | 287 // On ARM we have to move the value into a register to do anything |
296 // with it. | 288 // with it. |
297 Move(result_register(), slot); | 289 Move(result_register(), slot); |
298 Apply(context, result_register()); | 290 Apply(context, result_register()); |
299 break; | 291 break; |
300 } | 292 } |
301 } | 293 } |
302 | 294 |
303 | 295 |
304 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 296 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
305 switch (context) { | 297 switch (context) { |
306 case Expression::kUninitialized: | 298 case Expression::kUninitialized: |
307 UNREACHABLE(); | 299 UNREACHABLE(); |
308 case Expression::kEffect: | 300 case Expression::kEffect: |
309 break; | 301 break; |
310 // Nothing to do. | 302 // Nothing to do. |
311 case Expression::kValue: | 303 case Expression::kValue: |
312 case Expression::kTest: | 304 case Expression::kTest: |
313 case Expression::kValueTest: | |
314 case Expression::kTestValue: | |
315 // On ARM we have to move the value into a register to do anything | 305 // On ARM we have to move the value into a register to do anything |
316 // with it. | 306 // with it. |
317 __ mov(result_register(), Operand(lit->handle())); | 307 __ mov(result_register(), Operand(lit->handle())); |
318 Apply(context, result_register()); | 308 Apply(context, result_register()); |
319 break; | 309 break; |
320 } | 310 } |
321 } | 311 } |
322 | 312 |
323 | 313 |
324 void FullCodeGenerator::ApplyTOS(Expression::Context context) { | 314 void FullCodeGenerator::ApplyTOS(Expression::Context context) { |
325 switch (context) { | 315 switch (context) { |
326 case Expression::kUninitialized: | 316 case Expression::kUninitialized: |
327 UNREACHABLE(); | 317 UNREACHABLE(); |
328 | 318 |
329 case Expression::kEffect: | 319 case Expression::kEffect: |
330 __ Drop(1); | 320 __ Drop(1); |
331 break; | 321 break; |
332 | 322 |
333 case Expression::kValue: | 323 case Expression::kValue: |
334 switch (location_) { | 324 switch (location_) { |
335 case kAccumulator: | 325 case kAccumulator: |
336 __ pop(result_register()); | 326 __ pop(result_register()); |
337 break; | 327 break; |
338 case kStack: | 328 case kStack: |
339 break; | 329 break; |
340 } | 330 } |
341 break; | 331 break; |
342 | 332 |
343 case Expression::kValueTest: | |
344 case Expression::kTestValue: | |
345 // Duplicate the value on the stack in case it's needed. | |
346 __ ldr(ip, MemOperand(sp)); | |
347 __ push(ip); | |
348 // Fall through. | |
349 | |
350 case Expression::kTest: | 333 case Expression::kTest: |
351 DoTest(context); | 334 __ pop(result_register()); |
| 335 DoTest(true_label_, false_label_, NULL); |
352 break; | 336 break; |
353 } | 337 } |
354 } | 338 } |
355 | 339 |
356 | 340 |
357 void FullCodeGenerator::DropAndApply(int count, | 341 void FullCodeGenerator::DropAndApply(int count, |
358 Expression::Context context, | 342 Expression::Context context, |
359 Register reg) { | 343 Register reg) { |
360 ASSERT(count > 0); | 344 ASSERT(count > 0); |
361 ASSERT(!reg.is(sp)); | 345 ASSERT(!reg.is(sp)); |
(...skipping 12 matching lines...) Expand all Loading... |
374 if (!reg.is(result_register())) __ mov(result_register(), reg); | 358 if (!reg.is(result_register())) __ mov(result_register(), reg); |
375 break; | 359 break; |
376 case kStack: | 360 case kStack: |
377 if (count > 1) __ Drop(count - 1); | 361 if (count > 1) __ Drop(count - 1); |
378 __ str(reg, MemOperand(sp)); | 362 __ str(reg, MemOperand(sp)); |
379 break; | 363 break; |
380 } | 364 } |
381 break; | 365 break; |
382 | 366 |
383 case Expression::kTest: | 367 case Expression::kTest: |
384 if (count > 1) __ Drop(count - 1); | 368 __ Drop(count); |
385 __ str(reg, MemOperand(sp)); | 369 if (!reg.is(result_register())) __ mov(result_register(), reg); |
386 DoTest(context); | 370 DoTest(true_label_, false_label_, NULL); |
387 break; | |
388 | |
389 case Expression::kValueTest: | |
390 case Expression::kTestValue: | |
391 if (count == 1) { | |
392 __ str(reg, MemOperand(sp)); | |
393 __ push(reg); | |
394 } else { // count > 1 | |
395 __ Drop(count - 2); | |
396 __ str(reg, MemOperand(sp, kPointerSize)); | |
397 __ str(reg, MemOperand(sp)); | |
398 } | |
399 DoTest(context); | |
400 break; | 371 break; |
401 } | 372 } |
402 } | 373 } |
403 | 374 |
404 void FullCodeGenerator::PrepareTest(Label* materialize_true, | 375 void FullCodeGenerator::PrepareTest(Label* materialize_true, |
405 Label* materialize_false, | 376 Label* materialize_false, |
406 Label** if_true, | 377 Label** if_true, |
407 Label** if_false) { | 378 Label** if_false) { |
408 switch (context_) { | 379 switch (context_) { |
409 case Expression::kUninitialized: | 380 case Expression::kUninitialized: |
410 UNREACHABLE(); | 381 UNREACHABLE(); |
411 break; | 382 break; |
412 case Expression::kEffect: | 383 case Expression::kEffect: |
413 // In an effect context, the true and the false case branch to the | 384 // In an effect context, the true and the false case branch to the |
414 // same label. | 385 // same label. |
415 *if_true = *if_false = materialize_true; | 386 *if_true = *if_false = materialize_true; |
416 break; | 387 break; |
417 case Expression::kValue: | 388 case Expression::kValue: |
418 *if_true = materialize_true; | 389 *if_true = materialize_true; |
419 *if_false = materialize_false; | 390 *if_false = materialize_false; |
420 break; | 391 break; |
421 case Expression::kTest: | 392 case Expression::kTest: |
422 *if_true = true_label_; | 393 *if_true = true_label_; |
423 *if_false = false_label_; | 394 *if_false = false_label_; |
424 break; | 395 break; |
425 case Expression::kValueTest: | |
426 *if_true = materialize_true; | |
427 *if_false = false_label_; | |
428 break; | |
429 case Expression::kTestValue: | |
430 *if_true = true_label_; | |
431 *if_false = materialize_false; | |
432 break; | |
433 } | 396 } |
434 } | 397 } |
435 | 398 |
436 | 399 |
437 void FullCodeGenerator::Apply(Expression::Context context, | 400 void FullCodeGenerator::Apply(Expression::Context context, |
438 Label* materialize_true, | 401 Label* materialize_true, |
439 Label* materialize_false) { | 402 Label* materialize_false) { |
440 switch (context) { | 403 switch (context) { |
441 case Expression::kUninitialized: | 404 case Expression::kUninitialized: |
442 | 405 |
(...skipping 21 matching lines...) Expand all Loading... |
464 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 427 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
465 __ push(ip); | 428 __ push(ip); |
466 break; | 429 break; |
467 } | 430 } |
468 __ bind(&done); | 431 __ bind(&done); |
469 break; | 432 break; |
470 } | 433 } |
471 | 434 |
472 case Expression::kTest: | 435 case Expression::kTest: |
473 break; | 436 break; |
474 | |
475 case Expression::kValueTest: | |
476 __ bind(materialize_true); | |
477 switch (location_) { | |
478 case kAccumulator: | |
479 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); | |
480 break; | |
481 case kStack: | |
482 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | |
483 __ push(ip); | |
484 break; | |
485 } | |
486 __ jmp(true_label_); | |
487 break; | |
488 | |
489 case Expression::kTestValue: | |
490 __ bind(materialize_false); | |
491 switch (location_) { | |
492 case kAccumulator: | |
493 __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); | |
494 break; | |
495 case kStack: | |
496 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | |
497 __ push(ip); | |
498 break; | |
499 } | |
500 __ jmp(false_label_); | |
501 break; | |
502 } | 437 } |
503 } | 438 } |
504 | 439 |
505 | 440 |
506 // 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 |
507 // a given expression context. | 442 // a given expression context. |
508 void FullCodeGenerator::Apply(Expression::Context context, bool flag) { | 443 void FullCodeGenerator::Apply(Expression::Context context, bool flag) { |
509 switch (context) { | 444 switch (context) { |
510 case Expression::kUninitialized: | 445 case Expression::kUninitialized: |
511 UNREACHABLE(); | 446 UNREACHABLE(); |
(...skipping 10 matching lines...) Expand all Loading... |
522 case kStack: | 457 case kStack: |
523 __ LoadRoot(ip, value_root_index); | 458 __ LoadRoot(ip, value_root_index); |
524 __ push(ip); | 459 __ push(ip); |
525 break; | 460 break; |
526 } | 461 } |
527 break; | 462 break; |
528 } | 463 } |
529 case Expression::kTest: | 464 case Expression::kTest: |
530 __ b(flag ? true_label_ : false_label_); | 465 __ b(flag ? true_label_ : false_label_); |
531 break; | 466 break; |
532 case Expression::kTestValue: | |
533 switch (location_) { | |
534 case kAccumulator: | |
535 // If value is false it's needed. | |
536 if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); | |
537 break; | |
538 case kStack: | |
539 // If value is false it's needed. | |
540 if (!flag) { | |
541 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | |
542 __ push(ip); | |
543 } | |
544 break; | |
545 } | |
546 __ b(flag ? true_label_ : false_label_); | |
547 break; | |
548 case Expression::kValueTest: | |
549 switch (location_) { | |
550 case kAccumulator: | |
551 // If value is true it's needed. | |
552 if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); | |
553 break; | |
554 case kStack: | |
555 // If value is true it's needed. | |
556 if (flag) { | |
557 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | |
558 __ push(ip); | |
559 } | |
560 break; | |
561 } | |
562 __ b(flag ? true_label_ : false_label_); | |
563 break; | |
564 } | 467 } |
565 } | 468 } |
566 | 469 |
567 | 470 |
568 void FullCodeGenerator::DoTest(Expression::Context context) { | 471 void FullCodeGenerator::DoTest(Label* if_true, |
569 // The value to test is pushed on the stack, and duplicated on the stack | 472 Label* if_false, |
570 // if necessary (for value/test and test/value contexts). | 473 Label* fall_through) { |
571 ASSERT_NE(NULL, true_label_); | |
572 ASSERT_NE(NULL, false_label_); | |
573 | |
574 // Call the runtime to find the boolean value of the source and then | 474 // Call the runtime to find the boolean value of the source and then |
575 // translate it into control flow to the pair of labels. | 475 // translate it into control flow to the pair of labels. |
| 476 __ push(result_register()); |
576 __ CallRuntime(Runtime::kToBool, 1); | 477 __ CallRuntime(Runtime::kToBool, 1); |
577 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 478 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
578 __ cmp(r0, ip); | 479 __ cmp(r0, ip); |
| 480 Split(eq, if_true, if_false, fall_through); |
| 481 } |
579 | 482 |
580 // Complete based on the context. | |
581 switch (context) { | |
582 case Expression::kUninitialized: | |
583 case Expression::kEffect: | |
584 case Expression::kValue: | |
585 UNREACHABLE(); | |
586 | 483 |
587 case Expression::kTest: | 484 void FullCodeGenerator::Split(Condition cc, |
588 __ b(eq, true_label_); | 485 Label* if_true, |
589 __ jmp(false_label_); | 486 Label* if_false, |
590 break; | 487 Label* fall_through) { |
591 | 488 if (if_false == fall_through) { |
592 case Expression::kValueTest: { | 489 __ b(cc, if_true); |
593 Label discard; | 490 } else if (if_true == fall_through) { |
594 switch (location_) { | 491 __ b(NegateCondition(cc), if_false); |
595 case kAccumulator: | 492 } else { |
596 __ b(ne, &discard); | 493 __ b(cc, if_true); |
597 __ pop(result_register()); | 494 __ b(if_false); |
598 __ jmp(true_label_); | |
599 break; | |
600 case kStack: | |
601 __ b(eq, true_label_); | |
602 break; | |
603 } | |
604 __ bind(&discard); | |
605 __ Drop(1); | |
606 __ jmp(false_label_); | |
607 break; | |
608 } | |
609 | |
610 case Expression::kTestValue: { | |
611 Label discard; | |
612 switch (location_) { | |
613 case kAccumulator: | |
614 __ b(eq, &discard); | |
615 __ pop(result_register()); | |
616 __ jmp(false_label_); | |
617 break; | |
618 case kStack: | |
619 __ b(ne, false_label_); | |
620 break; | |
621 } | |
622 __ bind(&discard); | |
623 __ Drop(1); | |
624 __ jmp(true_label_); | |
625 break; | |
626 } | |
627 } | 495 } |
628 } | 496 } |
629 | 497 |
630 | 498 |
631 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 499 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
632 switch (slot->type()) { | 500 switch (slot->type()) { |
633 case Slot::PARAMETER: | 501 case Slot::PARAMETER: |
634 case Slot::LOCAL: | 502 case Slot::LOCAL: |
635 return MemOperand(fp, SlotOffset(slot)); | 503 return MemOperand(fp, SlotOffset(slot)); |
636 case Slot::CONTEXT: { | 504 case Slot::CONTEXT: { |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 | 968 |
1101 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 969 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1102 Comment cmnt(masm_, "[ RegExpLiteral"); | 970 Comment cmnt(masm_, "[ RegExpLiteral"); |
1103 Label materialized; | 971 Label materialized; |
1104 // Registers will be used as follows: | 972 // Registers will be used as follows: |
1105 // r4 = JS function, literals array | 973 // r4 = JS function, literals array |
1106 // r3 = literal index | 974 // r3 = literal index |
1107 // r2 = RegExp pattern | 975 // r2 = RegExp pattern |
1108 // r1 = RegExp flags | 976 // r1 = RegExp flags |
1109 // r0 = temp + materialized value (RegExp literal) | 977 // r0 = temp + materialized value (RegExp literal) |
1110 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 978 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
1111 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 979 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
1112 int literal_offset = | 980 int literal_offset = |
1113 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 981 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
1114 __ ldr(r0, FieldMemOperand(r4, literal_offset)); | 982 __ ldr(r0, FieldMemOperand(r4, literal_offset)); |
1115 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 983 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
1116 __ cmp(r0, ip); | 984 __ cmp(r0, ip); |
1117 __ b(ne, &materialized); | 985 __ b(ne, &materialized); |
| 986 |
| 987 // Create regexp literal using runtime function. |
| 988 // Result will be in r0. |
1118 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); | 989 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); |
1119 __ mov(r2, Operand(expr->pattern())); | 990 __ mov(r2, Operand(expr->pattern())); |
1120 __ mov(r1, Operand(expr->flags())); | 991 __ mov(r1, Operand(expr->flags())); |
1121 __ Push(r4, r3, r2, r1); | 992 __ Push(r4, r3, r2, r1); |
1122 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 993 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 994 |
1123 __ bind(&materialized); | 995 __ bind(&materialized); |
1124 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 996 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
1125 __ push(r0); | 997 __ push(r0); |
1126 __ mov(r0, Operand(Smi::FromInt(size))); | 998 __ mov(r0, Operand(Smi::FromInt(size))); |
1127 __ push(r0); | 999 __ push(r0); |
1128 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 1000 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 1001 |
1129 // After this, registers are used as follows: | 1002 // After this, registers are used as follows: |
1130 // r0: Newly allocated regexp. | 1003 // r0: Newly allocated regexp. |
1131 // r1: Materialized regexp | 1004 // r1: Materialized regexp. |
1132 // r2: temp. | 1005 // r2: temp. |
1133 __ pop(r1); | 1006 __ pop(r1); |
1134 __ CopyFields(r0, r1, r2.bit(), size / kPointerSize); | 1007 __ CopyFields(r0, r1, r2.bit(), size / kPointerSize); |
1135 Apply(context_, r0); | 1008 Apply(context_, r0); |
1136 } | 1009 } |
1137 | 1010 |
1138 | 1011 |
1139 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 1012 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
1140 Comment cmnt(masm_, "[ ObjectLiteral"); | 1013 Comment cmnt(masm_, "[ ObjectLiteral"); |
1141 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1014 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1878 ASSERT(args->length() == 1); | 1751 ASSERT(args->length() == 1); |
1879 | 1752 |
1880 VisitForValue(args->at(0), kAccumulator); | 1753 VisitForValue(args->at(0), kAccumulator); |
1881 | 1754 |
1882 Label materialize_true, materialize_false; | 1755 Label materialize_true, materialize_false; |
1883 Label* if_true = NULL; | 1756 Label* if_true = NULL; |
1884 Label* if_false = NULL; | 1757 Label* if_false = NULL; |
1885 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1758 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1886 | 1759 |
1887 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); | 1760 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); |
1888 __ b(eq, if_true); | 1761 Split(eq, if_true, if_false, NULL); |
1889 __ b(if_false); | |
1890 | 1762 |
1891 Apply(context_, if_true, if_false); | 1763 Apply(context_, if_true, if_false); |
1892 } | 1764 } |
1893 | 1765 |
1894 | 1766 |
1895 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { | 1767 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { |
1896 ASSERT(args->length() == 1); | 1768 ASSERT(args->length() == 1); |
1897 | 1769 |
1898 VisitForValue(args->at(0), kAccumulator); | 1770 VisitForValue(args->at(0), kAccumulator); |
1899 | 1771 |
1900 Label materialize_true, materialize_false; | 1772 Label materialize_true, materialize_false; |
1901 Label* if_true = NULL; | 1773 Label* if_true = NULL; |
1902 Label* if_false = NULL; | 1774 Label* if_false = NULL; |
1903 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1775 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1904 __ BranchOnSmi(r0, if_false); | 1776 __ BranchOnSmi(r0, if_false); |
1905 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1777 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
1906 __ cmp(r0, ip); | 1778 __ cmp(r0, ip); |
1907 __ b(eq, if_true); | 1779 __ b(eq, if_true); |
1908 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 1780 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
1909 // Undetectable objects behave like undefined when tested with typeof. | 1781 // Undetectable objects behave like undefined when tested with typeof. |
1910 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); | 1782 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); |
1911 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 1783 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
1912 __ b(ne, if_false); | 1784 __ b(ne, if_false); |
1913 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 1785 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
1914 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); | 1786 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); |
1915 __ b(lt, if_false); | 1787 __ b(lt, if_false); |
1916 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); | 1788 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); |
1917 __ b(le, if_true); | 1789 Split(le, if_true, if_false, NULL); |
1918 __ b(if_false); | |
1919 | 1790 |
1920 Apply(context_, if_true, if_false); | 1791 Apply(context_, if_true, if_false); |
1921 } | 1792 } |
1922 | 1793 |
1923 | 1794 |
1924 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { | 1795 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { |
1925 ASSERT(args->length() == 1); | 1796 ASSERT(args->length() == 1); |
1926 | 1797 |
1927 VisitForValue(args->at(0), kAccumulator); | 1798 VisitForValue(args->at(0), kAccumulator); |
1928 | 1799 |
1929 Label materialize_true, materialize_false; | 1800 Label materialize_true, materialize_false; |
1930 Label* if_true = NULL; | 1801 Label* if_true = NULL; |
1931 Label* if_false = NULL; | 1802 Label* if_false = NULL; |
1932 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1803 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1933 | 1804 |
1934 __ BranchOnSmi(r0, if_false); | 1805 __ BranchOnSmi(r0, if_false); |
1935 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); | 1806 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |
1936 __ b(ge, if_true); | 1807 Split(ge, if_true, if_false, NULL); |
1937 __ b(if_false); | |
1938 | 1808 |
1939 Apply(context_, if_true, if_false); | 1809 Apply(context_, if_true, if_false); |
1940 } | 1810 } |
1941 | 1811 |
1942 | 1812 |
1943 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 1813 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
1944 ASSERT(args->length() == 1); | 1814 ASSERT(args->length() == 1); |
1945 | 1815 |
1946 VisitForValue(args->at(0), kAccumulator); | 1816 VisitForValue(args->at(0), kAccumulator); |
1947 | 1817 |
1948 Label materialize_true, materialize_false; | 1818 Label materialize_true, materialize_false; |
1949 Label* if_true = NULL; | 1819 Label* if_true = NULL; |
1950 Label* if_false = NULL; | 1820 Label* if_false = NULL; |
1951 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1821 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1952 | 1822 |
1953 __ BranchOnSmi(r0, if_false); | 1823 __ BranchOnSmi(r0, if_false); |
1954 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 1824 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
1955 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); | 1825 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); |
1956 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 1826 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
1957 __ b(ne, if_true); | 1827 Split(ne, if_true, if_false, NULL); |
1958 __ b(if_false); | |
1959 | 1828 |
1960 Apply(context_, if_true, if_false); | 1829 Apply(context_, if_true, if_false); |
1961 } | 1830 } |
1962 | 1831 |
1963 | 1832 |
1964 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 1833 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
1965 ZoneList<Expression*>* args) { | 1834 ZoneList<Expression*>* args) { |
1966 | 1835 |
1967 ASSERT(args->length() == 1); | 1836 ASSERT(args->length() == 1); |
1968 | 1837 |
(...skipping 17 matching lines...) Expand all Loading... |
1986 | 1855 |
1987 VisitForValue(args->at(0), kAccumulator); | 1856 VisitForValue(args->at(0), kAccumulator); |
1988 | 1857 |
1989 Label materialize_true, materialize_false; | 1858 Label materialize_true, materialize_false; |
1990 Label* if_true = NULL; | 1859 Label* if_true = NULL; |
1991 Label* if_false = NULL; | 1860 Label* if_false = NULL; |
1992 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1861 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1993 | 1862 |
1994 __ BranchOnSmi(r0, if_false); | 1863 __ BranchOnSmi(r0, if_false); |
1995 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); | 1864 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); |
1996 __ b(eq, if_true); | 1865 Split(eq, if_true, if_false, NULL); |
1997 __ b(if_false); | |
1998 | 1866 |
1999 Apply(context_, if_true, if_false); | 1867 Apply(context_, if_true, if_false); |
2000 } | 1868 } |
2001 | 1869 |
2002 | 1870 |
2003 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { | 1871 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { |
2004 ASSERT(args->length() == 1); | 1872 ASSERT(args->length() == 1); |
2005 | 1873 |
2006 VisitForValue(args->at(0), kAccumulator); | 1874 VisitForValue(args->at(0), kAccumulator); |
2007 | 1875 |
2008 Label materialize_true, materialize_false; | 1876 Label materialize_true, materialize_false; |
2009 Label* if_true = NULL; | 1877 Label* if_true = NULL; |
2010 Label* if_false = NULL; | 1878 Label* if_false = NULL; |
2011 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1879 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2012 | 1880 |
2013 __ BranchOnSmi(r0, if_false); | 1881 __ BranchOnSmi(r0, if_false); |
2014 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | 1882 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
2015 __ b(eq, if_true); | 1883 Split(eq, if_true, if_false, NULL); |
2016 __ b(if_false); | |
2017 | 1884 |
2018 Apply(context_, if_true, if_false); | 1885 Apply(context_, if_true, if_false); |
2019 } | 1886 } |
2020 | 1887 |
2021 | 1888 |
2022 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { | 1889 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { |
2023 ASSERT(args->length() == 1); | 1890 ASSERT(args->length() == 1); |
2024 | 1891 |
2025 VisitForValue(args->at(0), kAccumulator); | 1892 VisitForValue(args->at(0), kAccumulator); |
2026 | 1893 |
2027 Label materialize_true, materialize_false; | 1894 Label materialize_true, materialize_false; |
2028 Label* if_true = NULL; | 1895 Label* if_true = NULL; |
2029 Label* if_false = NULL; | 1896 Label* if_false = NULL; |
2030 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1897 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2031 | 1898 |
2032 __ BranchOnSmi(r0, if_false); | 1899 __ BranchOnSmi(r0, if_false); |
2033 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); | 1900 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); |
2034 __ b(eq, if_true); | 1901 Split(eq, if_true, if_false, NULL); |
2035 __ b(if_false); | |
2036 | 1902 |
2037 Apply(context_, if_true, if_false); | 1903 Apply(context_, if_true, if_false); |
2038 } | 1904 } |
2039 | 1905 |
2040 | 1906 |
2041 | 1907 |
2042 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { | 1908 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { |
2043 ASSERT(args->length() == 0); | 1909 ASSERT(args->length() == 0); |
2044 | 1910 |
2045 Label materialize_true, materialize_false; | 1911 Label materialize_true, materialize_false; |
2046 Label* if_true = NULL; | 1912 Label* if_true = NULL; |
2047 Label* if_false = NULL; | 1913 Label* if_false = NULL; |
2048 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1914 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2049 | 1915 |
2050 // Get the frame pointer for the calling frame. | 1916 // Get the frame pointer for the calling frame. |
2051 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1917 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
2052 | 1918 |
2053 // Skip the arguments adaptor frame if it exists. | 1919 // Skip the arguments adaptor frame if it exists. |
2054 Label check_frame_marker; | 1920 Label check_frame_marker; |
2055 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 1921 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
2056 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1922 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
2057 __ b(ne, &check_frame_marker); | 1923 __ b(ne, &check_frame_marker); |
2058 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); | 1924 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); |
2059 | 1925 |
2060 // Check the marker in the calling frame. | 1926 // Check the marker in the calling frame. |
2061 __ bind(&check_frame_marker); | 1927 __ bind(&check_frame_marker); |
2062 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); | 1928 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); |
2063 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 1929 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); |
2064 __ b(eq, if_true); | 1930 Split(eq, if_true, if_false, NULL); |
2065 __ b(if_false); | |
2066 | 1931 |
2067 Apply(context_, if_true, if_false); | 1932 Apply(context_, if_true, if_false); |
2068 } | 1933 } |
2069 | 1934 |
2070 | 1935 |
2071 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { | 1936 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { |
2072 ASSERT(args->length() == 2); | 1937 ASSERT(args->length() == 2); |
2073 | 1938 |
2074 // Load the two objects into registers and perform the comparison. | 1939 // Load the two objects into registers and perform the comparison. |
2075 VisitForValue(args->at(0), kStack); | 1940 VisitForValue(args->at(0), kStack); |
2076 VisitForValue(args->at(1), kAccumulator); | 1941 VisitForValue(args->at(1), kAccumulator); |
2077 | 1942 |
2078 Label materialize_true, materialize_false; | 1943 Label materialize_true, materialize_false; |
2079 Label* if_true = NULL; | 1944 Label* if_true = NULL; |
2080 Label* if_false = NULL; | 1945 Label* if_false = NULL; |
2081 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1946 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2082 | 1947 |
2083 __ pop(r1); | 1948 __ pop(r1); |
2084 __ cmp(r0, r1); | 1949 __ cmp(r0, r1); |
2085 __ b(eq, if_true); | 1950 Split(eq, if_true, if_false, NULL); |
2086 __ b(if_false); | |
2087 | 1951 |
2088 Apply(context_, if_true, if_false); | 1952 Apply(context_, if_true, if_false); |
2089 } | 1953 } |
2090 | 1954 |
2091 | 1955 |
2092 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 1956 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
2093 ASSERT(args->length() == 1); | 1957 ASSERT(args->length() == 1); |
2094 | 1958 |
2095 // ArgumentsAccessStub expects the key in edx and the formal | 1959 // ArgumentsAccessStub expects the key in edx and the formal |
2096 // parameter count in eax. | 1960 // parameter count in eax. |
(...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2745 case Expression::kValue: | 2609 case Expression::kValue: |
2746 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); | 2610 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); |
2747 switch (location_) { | 2611 switch (location_) { |
2748 case kAccumulator: | 2612 case kAccumulator: |
2749 break; | 2613 break; |
2750 case kStack: | 2614 case kStack: |
2751 __ push(result_register()); | 2615 __ push(result_register()); |
2752 break; | 2616 break; |
2753 } | 2617 } |
2754 break; | 2618 break; |
2755 case Expression::kTestValue: | |
2756 // Value is false so it's needed. | |
2757 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); | |
2758 switch (location_) { | |
2759 case kAccumulator: | |
2760 break; | |
2761 case kStack: | |
2762 __ push(result_register()); | |
2763 break; | |
2764 } | |
2765 // Fall through. | |
2766 case Expression::kTest: | 2619 case Expression::kTest: |
2767 case Expression::kValueTest: | |
2768 __ jmp(false_label_); | 2620 __ jmp(false_label_); |
2769 break; | 2621 break; |
2770 } | 2622 } |
2771 break; | 2623 break; |
2772 } | 2624 } |
2773 | 2625 |
2774 case Token::NOT: { | 2626 case Token::NOT: { |
2775 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); | 2627 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); |
2776 Label materialize_true, materialize_false; | 2628 Label materialize_true, materialize_false; |
2777 Label* if_true = NULL; | 2629 Label* if_true = NULL; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2938 // Save result for postfix expressions. | 2790 // Save result for postfix expressions. |
2939 if (expr->is_postfix()) { | 2791 if (expr->is_postfix()) { |
2940 switch (context_) { | 2792 switch (context_) { |
2941 case Expression::kUninitialized: | 2793 case Expression::kUninitialized: |
2942 UNREACHABLE(); | 2794 UNREACHABLE(); |
2943 case Expression::kEffect: | 2795 case Expression::kEffect: |
2944 // Do not save result. | 2796 // Do not save result. |
2945 break; | 2797 break; |
2946 case Expression::kValue: | 2798 case Expression::kValue: |
2947 case Expression::kTest: | 2799 case Expression::kTest: |
2948 case Expression::kValueTest: | |
2949 case Expression::kTestValue: | |
2950 // Save the result on the stack. If we have a named or keyed property | 2800 // Save the result on the stack. If we have a named or keyed property |
2951 // we store the result under the receiver that is currently on top | 2801 // we store the result under the receiver that is currently on top |
2952 // of the stack. | 2802 // of the stack. |
2953 switch (assign_type) { | 2803 switch (assign_type) { |
2954 case VARIABLE: | 2804 case VARIABLE: |
2955 __ push(r0); | 2805 __ push(r0); |
2956 break; | 2806 break; |
2957 case NAMED_PROPERTY: | 2807 case NAMED_PROPERTY: |
2958 __ str(r0, MemOperand(sp, kPointerSize)); | 2808 __ str(r0, MemOperand(sp, kPointerSize)); |
2959 break; | 2809 break; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3027 } | 2877 } |
3028 } else { | 2878 } else { |
3029 Apply(context_, r0); | 2879 Apply(context_, r0); |
3030 } | 2880 } |
3031 break; | 2881 break; |
3032 } | 2882 } |
3033 } | 2883 } |
3034 } | 2884 } |
3035 | 2885 |
3036 | 2886 |
3037 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | |
3038 Comment cmnt(masm_, "[ BinaryOperation"); | |
3039 switch (expr->op()) { | |
3040 case Token::COMMA: | |
3041 VisitForEffect(expr->left()); | |
3042 Visit(expr->right()); | |
3043 break; | |
3044 | |
3045 case Token::OR: | |
3046 case Token::AND: | |
3047 EmitLogicalOperation(expr); | |
3048 break; | |
3049 | |
3050 case Token::ADD: | |
3051 case Token::SUB: | |
3052 case Token::DIV: | |
3053 case Token::MOD: | |
3054 case Token::MUL: | |
3055 case Token::BIT_OR: | |
3056 case Token::BIT_AND: | |
3057 case Token::BIT_XOR: | |
3058 case Token::SHL: | |
3059 case Token::SHR: | |
3060 case Token::SAR: | |
3061 VisitForValue(expr->left(), kStack); | |
3062 VisitForValue(expr->right(), kAccumulator); | |
3063 EmitBinaryOp(expr->op(), context_); | |
3064 break; | |
3065 | |
3066 default: | |
3067 UNREACHABLE(); | |
3068 } | |
3069 } | |
3070 | |
3071 | |
3072 void FullCodeGenerator::EmitNullCompare(bool strict, | 2887 void FullCodeGenerator::EmitNullCompare(bool strict, |
3073 Register obj, | 2888 Register obj, |
3074 Register null_const, | 2889 Register null_const, |
3075 Label* if_true, | 2890 Label* if_true, |
3076 Label* if_false, | 2891 Label* if_false, |
3077 Register scratch) { | 2892 Register scratch) { |
3078 __ cmp(obj, null_const); | 2893 __ cmp(obj, null_const); |
3079 if (strict) { | 2894 if (strict) { |
3080 __ b(eq, if_true); | 2895 Split(eq, if_true, if_false, NULL); |
3081 } else { | 2896 } else { |
3082 __ b(eq, if_true); | 2897 __ b(eq, if_true); |
3083 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 2898 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
3084 __ cmp(obj, ip); | 2899 __ cmp(obj, ip); |
3085 __ b(eq, if_true); | 2900 __ b(eq, if_true); |
3086 __ BranchOnSmi(obj, if_false); | 2901 __ BranchOnSmi(obj, if_false); |
3087 // It can be an undetectable object. | 2902 // It can be an undetectable object. |
3088 __ ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); | 2903 __ ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); |
3089 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); | 2904 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); |
3090 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); | 2905 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); |
3091 __ b(ne, if_true); | 2906 Split(ne, if_true, if_false, NULL); |
3092 } | 2907 } |
3093 __ jmp(if_false); | |
3094 } | 2908 } |
3095 | 2909 |
3096 | 2910 |
3097 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 2911 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
3098 Comment cmnt(masm_, "[ CompareOperation"); | 2912 Comment cmnt(masm_, "[ CompareOperation"); |
3099 | 2913 |
3100 // Always perform the comparison for its control flow. Pack the result | 2914 // Always perform the comparison for its control flow. Pack the result |
3101 // into the expression's context after the comparison is performed. | 2915 // into the expression's context after the comparison is performed. |
3102 | 2916 |
3103 Label materialize_true, materialize_false; | 2917 Label materialize_true, materialize_false; |
3104 Label* if_true = NULL; | 2918 Label* if_true = NULL; |
3105 Label* if_false = NULL; | 2919 Label* if_false = NULL; |
3106 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 2920 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
3107 | 2921 |
3108 VisitForValue(expr->left(), kStack); | 2922 VisitForValue(expr->left(), kStack); |
3109 switch (expr->op()) { | 2923 switch (expr->op()) { |
3110 case Token::IN: | 2924 case Token::IN: |
3111 VisitForValue(expr->right(), kStack); | 2925 VisitForValue(expr->right(), kStack); |
3112 __ InvokeBuiltin(Builtins::IN, CALL_JS); | 2926 __ InvokeBuiltin(Builtins::IN, CALL_JS); |
3113 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 2927 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
3114 __ cmp(r0, ip); | 2928 __ cmp(r0, ip); |
3115 __ b(eq, if_true); | 2929 Split(eq, if_true, if_false, NULL); |
3116 __ jmp(if_false); | |
3117 break; | 2930 break; |
3118 | 2931 |
3119 case Token::INSTANCEOF: { | 2932 case Token::INSTANCEOF: { |
3120 VisitForValue(expr->right(), kStack); | 2933 VisitForValue(expr->right(), kStack); |
3121 InstanceofStub stub; | 2934 InstanceofStub stub; |
3122 __ CallStub(&stub); | 2935 __ CallStub(&stub); |
| 2936 // The stub returns 0 for true. |
3123 __ tst(r0, r0); | 2937 __ tst(r0, r0); |
3124 __ b(eq, if_true); // The stub returns 0 for true. | 2938 Split(eq, if_true, if_false, NULL); |
3125 __ jmp(if_false); | |
3126 break; | 2939 break; |
3127 } | 2940 } |
3128 | 2941 |
3129 default: { | 2942 default: { |
3130 VisitForValue(expr->right(), kAccumulator); | 2943 VisitForValue(expr->right(), kAccumulator); |
3131 Condition cc = eq; | 2944 Condition cc = eq; |
3132 bool strict = false; | 2945 bool strict = false; |
3133 switch (expr->op()) { | 2946 switch (expr->op()) { |
3134 case Token::EQ_STRICT: | 2947 case Token::EQ_STRICT: |
3135 strict = true; | 2948 strict = true; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3184 __ orr(r2, r0, Operand(r1)); | 2997 __ orr(r2, r0, Operand(r1)); |
3185 __ BranchOnNotSmi(r2, &slow_case); | 2998 __ BranchOnNotSmi(r2, &slow_case); |
3186 __ cmp(r1, r0); | 2999 __ cmp(r1, r0); |
3187 __ b(cc, if_true); | 3000 __ b(cc, if_true); |
3188 __ jmp(if_false); | 3001 __ jmp(if_false); |
3189 | 3002 |
3190 __ bind(&slow_case); | 3003 __ bind(&slow_case); |
3191 CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0); | 3004 CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0); |
3192 __ CallStub(&stub); | 3005 __ CallStub(&stub); |
3193 __ cmp(r0, Operand(0)); | 3006 __ cmp(r0, Operand(0)); |
3194 __ b(cc, if_true); | 3007 Split(cc, if_true, if_false, NULL); |
3195 __ jmp(if_false); | |
3196 } | 3008 } |
3197 } | 3009 } |
3198 | 3010 |
3199 // Convert the result of the comparison into one expected for this | 3011 // Convert the result of the comparison into one expected for this |
3200 // expression's context. | 3012 // expression's context. |
3201 Apply(context_, if_true, if_false); | 3013 Apply(context_, if_true, if_false); |
3202 } | 3014 } |
3203 | 3015 |
3204 | 3016 |
3205 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 3017 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3251 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3063 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
3252 __ add(pc, r1, Operand(masm_->CodeObject())); | 3064 __ add(pc, r1, Operand(masm_->CodeObject())); |
3253 } | 3065 } |
3254 | 3066 |
3255 | 3067 |
3256 #undef __ | 3068 #undef __ |
3257 | 3069 |
3258 } } // namespace v8::internal | 3070 } } // namespace v8::internal |
3259 | 3071 |
3260 #endif // V8_TARGET_ARCH_ARM | 3072 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |