| 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 |