| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 return MemOperand(fp, -(index + 3) * kPointerSize + kPointerSize); | 457 return MemOperand(fp, -(index + 3) * kPointerSize + kPointerSize); |
| 458 } else { | 458 } else { |
| 459 // Incoming parameter. Skip the return address and the first word of | 459 // Incoming parameter. Skip the return address and the first word of |
| 460 // the double. | 460 // the double. |
| 461 return MemOperand(fp, -(index - 1) * kPointerSize + kPointerSize); | 461 return MemOperand(fp, -(index - 1) * kPointerSize + kPointerSize); |
| 462 } | 462 } |
| 463 } | 463 } |
| 464 | 464 |
| 465 | 465 |
| 466 void LCodeGen::WriteTranslation(LEnvironment* environment, | 466 void LCodeGen::WriteTranslation(LEnvironment* environment, |
| 467 Translation* translation, | 467 Translation* translation) { |
| 468 int* arguments_index, | |
| 469 int* arguments_count) { | |
| 470 if (environment == NULL) return; | 468 if (environment == NULL) return; |
| 471 | 469 |
| 472 // The translation includes one command per value in the environment. | 470 // The translation includes one command per value in the environment. |
| 473 int translation_size = environment->values()->length(); | 471 int translation_size = environment->values()->length(); |
| 474 // The output frame height does not include the parameters. | 472 // The output frame height does not include the parameters. |
| 475 int height = translation_size - environment->parameter_count(); | 473 int height = translation_size - environment->parameter_count(); |
| 476 | 474 |
| 477 // Function parameters are arguments to the outermost environment. The | 475 WriteTranslation(environment->outer(), translation); |
| 478 // arguments index points to the first element of a sequence of tagged | |
| 479 // values on the stack that represent the arguments. This needs to be | |
| 480 // kept in sync with the LArgumentsElements implementation. | |
| 481 *arguments_index = -environment->parameter_count(); | |
| 482 *arguments_count = environment->parameter_count(); | |
| 483 | |
| 484 WriteTranslation(environment->outer(), | |
| 485 translation, | |
| 486 arguments_index, | |
| 487 arguments_count); | |
| 488 int closure_id = *info()->closure() != *environment->closure() | 476 int closure_id = *info()->closure() != *environment->closure() |
| 489 ? DefineDeoptimizationLiteral(environment->closure()) | 477 ? DefineDeoptimizationLiteral(environment->closure()) |
| 490 : Translation::kSelfLiteralId; | 478 : Translation::kSelfLiteralId; |
| 491 | 479 |
| 492 switch (environment->frame_type()) { | 480 switch (environment->frame_type()) { |
| 493 case JS_FUNCTION: | 481 case JS_FUNCTION: |
| 494 translation->BeginJSFrame(environment->ast_id(), closure_id, height); | 482 translation->BeginJSFrame(environment->ast_id(), closure_id, height); |
| 495 break; | 483 break; |
| 496 case JS_CONSTRUCT: | 484 case JS_CONSTRUCT: |
| 497 translation->BeginConstructStubFrame(closure_id, translation_size); | 485 translation->BeginConstructStubFrame(closure_id, translation_size); |
| 498 break; | 486 break; |
| 499 case JS_GETTER: | 487 case JS_GETTER: |
| 500 ASSERT(translation_size == 1); | 488 ASSERT(translation_size == 1); |
| 501 ASSERT(height == 0); | 489 ASSERT(height == 0); |
| 502 translation->BeginGetterStubFrame(closure_id); | 490 translation->BeginGetterStubFrame(closure_id); |
| 503 break; | 491 break; |
| 504 case JS_SETTER: | 492 case JS_SETTER: |
| 505 ASSERT(translation_size == 2); | 493 ASSERT(translation_size == 2); |
| 506 ASSERT(height == 0); | 494 ASSERT(height == 0); |
| 507 translation->BeginSetterStubFrame(closure_id); | 495 translation->BeginSetterStubFrame(closure_id); |
| 508 break; | 496 break; |
| 509 case ARGUMENTS_ADAPTOR: | 497 case ARGUMENTS_ADAPTOR: |
| 510 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); | 498 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); |
| 511 break; | 499 break; |
| 512 } | 500 } |
| 513 | |
| 514 // Inlined frames which push their arguments cause the index to be | |
| 515 // bumped and a new stack area to be used for materialization. | |
| 516 if (environment->entry() != NULL && | |
| 517 environment->entry()->arguments_pushed()) { | |
| 518 *arguments_index = *arguments_index < 0 | |
| 519 ? GetStackSlotCount() | |
| 520 : *arguments_index + *arguments_count; | |
| 521 *arguments_count = environment->entry()->arguments_count() + 1; | |
| 522 } | |
| 523 | |
| 524 for (int i = 0; i < translation_size; ++i) { | 501 for (int i = 0; i < translation_size; ++i) { |
| 525 LOperand* value = environment->values()->at(i); | 502 LOperand* value = environment->values()->at(i); |
| 526 // spilled_registers_ and spilled_double_registers_ are either | 503 // spilled_registers_ and spilled_double_registers_ are either |
| 527 // both NULL or both set. | 504 // both NULL or both set. |
| 528 if (environment->spilled_registers() != NULL && value != NULL) { | 505 if (environment->spilled_registers() != NULL && value != NULL) { |
| 529 if (value->IsRegister() && | 506 if (value->IsRegister() && |
| 530 environment->spilled_registers()[value->index()] != NULL) { | 507 environment->spilled_registers()[value->index()] != NULL) { |
| 531 translation->MarkDuplicate(); | 508 translation->MarkDuplicate(); |
| 532 AddToTranslation(translation, | 509 AddToTranslation(translation, |
| 533 environment->spilled_registers()[value->index()], | 510 environment->spilled_registers()[value->index()], |
| 534 environment->HasTaggedValueAt(i), | 511 environment->HasTaggedValueAt(i), |
| 535 environment->HasUint32ValueAt(i), | 512 environment->HasUint32ValueAt(i)); |
| 536 *arguments_index, | |
| 537 *arguments_count); | |
| 538 } else if ( | 513 } else if ( |
| 539 value->IsDoubleRegister() && | 514 value->IsDoubleRegister() && |
| 540 environment->spilled_double_registers()[value->index()] != NULL) { | 515 environment->spilled_double_registers()[value->index()] != NULL) { |
| 541 translation->MarkDuplicate(); | 516 translation->MarkDuplicate(); |
| 542 AddToTranslation( | 517 AddToTranslation( |
| 543 translation, | 518 translation, |
| 544 environment->spilled_double_registers()[value->index()], | 519 environment->spilled_double_registers()[value->index()], |
| 545 false, | 520 false, |
| 546 false, | 521 false); |
| 547 *arguments_index, | |
| 548 *arguments_count); | |
| 549 } | 522 } |
| 550 } | 523 } |
| 551 | 524 |
| 552 AddToTranslation(translation, | 525 AddToTranslation(translation, |
| 553 value, | 526 value, |
| 554 environment->HasTaggedValueAt(i), | 527 environment->HasTaggedValueAt(i), |
| 555 environment->HasUint32ValueAt(i), | 528 environment->HasUint32ValueAt(i)); |
| 556 *arguments_index, | |
| 557 *arguments_count); | |
| 558 } | 529 } |
| 559 } | 530 } |
| 560 | 531 |
| 561 | 532 |
| 562 void LCodeGen::AddToTranslation(Translation* translation, | 533 void LCodeGen::AddToTranslation(Translation* translation, |
| 563 LOperand* op, | 534 LOperand* op, |
| 564 bool is_tagged, | 535 bool is_tagged, |
| 565 bool is_uint32, | 536 bool is_uint32) { |
| 566 int arguments_index, | |
| 567 int arguments_count) { | |
| 568 if (op == NULL) { | 537 if (op == NULL) { |
| 569 // TODO(twuerthinger): Introduce marker operands to indicate that this value | 538 // TODO(twuerthinger): Introduce marker operands to indicate that this value |
| 570 // is not present and must be reconstructed from the deoptimizer. Currently | 539 // is not present and must be reconstructed from the deoptimizer. Currently |
| 571 // this is only used for the arguments object. | 540 // this is only used for the arguments object. |
| 572 translation->StoreArgumentsObject(arguments_index, arguments_count); | 541 translation->StoreArgumentsObject(); |
| 573 } else if (op->IsStackSlot()) { | 542 } else if (op->IsStackSlot()) { |
| 574 if (is_tagged) { | 543 if (is_tagged) { |
| 575 translation->StoreStackSlot(op->index()); | 544 translation->StoreStackSlot(op->index()); |
| 576 } else if (is_uint32) { | 545 } else if (is_uint32) { |
| 577 translation->StoreUint32StackSlot(op->index()); | 546 translation->StoreUint32StackSlot(op->index()); |
| 578 } else { | 547 } else { |
| 579 translation->StoreInt32StackSlot(op->index()); | 548 translation->StoreInt32StackSlot(op->index()); |
| 580 } | 549 } |
| 581 } else if (op->IsDoubleStackSlot()) { | 550 } else if (op->IsDoubleStackSlot()) { |
| 582 translation->StoreDoubleStackSlot(op->index()); | 551 translation->StoreDoubleStackSlot(op->index()); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 // 0 ..................................................... size-1 | 637 // 0 ..................................................... size-1 |
| 669 // [parameters] [locals] [expression stack including arguments] | 638 // [parameters] [locals] [expression stack including arguments] |
| 670 | 639 |
| 671 // Layout of the translation: | 640 // Layout of the translation: |
| 672 // 0 ........................................................ size - 1 + 4 | 641 // 0 ........................................................ size - 1 + 4 |
| 673 // [expression stack including arguments] [locals] [4 words] [parameters] | 642 // [expression stack including arguments] [locals] [4 words] [parameters] |
| 674 // |>------------ translation_size ------------<| | 643 // |>------------ translation_size ------------<| |
| 675 | 644 |
| 676 int frame_count = 0; | 645 int frame_count = 0; |
| 677 int jsframe_count = 0; | 646 int jsframe_count = 0; |
| 678 int args_index = 0; | |
| 679 int args_count = 0; | |
| 680 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { | 647 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { |
| 681 ++frame_count; | 648 ++frame_count; |
| 682 if (e->frame_type() == JS_FUNCTION) { | 649 if (e->frame_type() == JS_FUNCTION) { |
| 683 ++jsframe_count; | 650 ++jsframe_count; |
| 684 } | 651 } |
| 685 } | 652 } |
| 686 Translation translation(&translations_, frame_count, jsframe_count, zone()); | 653 Translation translation(&translations_, frame_count, jsframe_count, |
| 687 WriteTranslation(environment, &translation, &args_index, &args_count); | 654 zone()); |
| 655 WriteTranslation(environment, &translation); |
| 688 int deoptimization_index = deoptimizations_.length(); | 656 int deoptimization_index = deoptimizations_.length(); |
| 689 int pc_offset = masm()->pc_offset(); | 657 int pc_offset = masm()->pc_offset(); |
| 690 environment->Register(deoptimization_index, | 658 environment->Register(deoptimization_index, |
| 691 translation.index(), | 659 translation.index(), |
| 692 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 660 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
| 693 deoptimizations_.Add(environment, zone()); | 661 deoptimizations_.Add(environment, zone()); |
| 694 } | 662 } |
| 695 } | 663 } |
| 696 | 664 |
| 697 | 665 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 944 } | 912 } |
| 945 | 913 |
| 946 | 914 |
| 947 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 915 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 948 // Nothing to do. | 916 // Nothing to do. |
| 949 } | 917 } |
| 950 | 918 |
| 951 | 919 |
| 952 void LCodeGen::DoModI(LModI* instr) { | 920 void LCodeGen::DoModI(LModI* instr) { |
| 953 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 921 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
| 954 Register dividend = ToRegister(instr->left()); | 922 Register dividend = ToRegister(instr->InputAt(0)); |
| 955 Register result = ToRegister(instr->result()); | 923 Register result = ToRegister(instr->result()); |
| 956 | 924 |
| 957 int32_t divisor = | 925 int32_t divisor = |
| 958 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 926 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
| 959 | 927 |
| 960 if (divisor < 0) divisor = -divisor; | 928 if (divisor < 0) divisor = -divisor; |
| 961 | 929 |
| 962 Label positive_dividend, done; | 930 Label positive_dividend, done; |
| 963 __ cmp(dividend, Operand(0)); | 931 __ cmp(dividend, Operand(0)); |
| 964 __ b(pl, &positive_dividend); | 932 __ b(pl, &positive_dividend); |
| 965 __ rsb(result, dividend, Operand(0)); | 933 __ rsb(result, dividend, Operand(0)); |
| 966 __ and_(result, result, Operand(divisor - 1), SetCC); | 934 __ and_(result, result, Operand(divisor - 1), SetCC); |
| 967 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 935 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 968 DeoptimizeIf(eq, instr->environment()); | 936 DeoptimizeIf(eq, instr->environment()); |
| 969 } | 937 } |
| 970 __ rsb(result, result, Operand(0)); | 938 __ rsb(result, result, Operand(0)); |
| 971 __ b(&done); | 939 __ b(&done); |
| 972 __ bind(&positive_dividend); | 940 __ bind(&positive_dividend); |
| 973 __ and_(result, dividend, Operand(divisor - 1)); | 941 __ and_(result, dividend, Operand(divisor - 1)); |
| 974 __ bind(&done); | 942 __ bind(&done); |
| 975 return; | 943 return; |
| 976 } | 944 } |
| 977 | 945 |
| 978 // These registers hold untagged 32 bit values. | 946 // These registers hold untagged 32 bit values. |
| 979 Register left = ToRegister(instr->left()); | 947 Register left = ToRegister(instr->InputAt(0)); |
| 980 Register right = ToRegister(instr->right()); | 948 Register right = ToRegister(instr->InputAt(1)); |
| 981 Register result = ToRegister(instr->result()); | 949 Register result = ToRegister(instr->result()); |
| 982 | 950 |
| 983 Register scratch = scratch0(); | 951 Register scratch = scratch0(); |
| 984 Register scratch2 = ToRegister(instr->temp()); | 952 Register scratch2 = ToRegister(instr->TempAt(0)); |
| 985 DwVfpRegister dividend = ToDoubleRegister(instr->temp2()); | 953 DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1)); |
| 986 DwVfpRegister divisor = ToDoubleRegister(instr->temp3()); | 954 DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2)); |
| 987 DwVfpRegister quotient = double_scratch0(); | 955 DwVfpRegister quotient = double_scratch0(); |
| 988 | 956 |
| 989 ASSERT(!dividend.is(divisor)); | 957 ASSERT(!dividend.is(divisor)); |
| 990 ASSERT(!dividend.is(quotient)); | 958 ASSERT(!dividend.is(quotient)); |
| 991 ASSERT(!divisor.is(quotient)); | 959 ASSERT(!divisor.is(quotient)); |
| 992 ASSERT(!scratch.is(left)); | 960 ASSERT(!scratch.is(left)); |
| 993 ASSERT(!scratch.is(right)); | 961 ASSERT(!scratch.is(right)); |
| 994 ASSERT(!scratch.is(result)); | 962 ASSERT(!scratch.is(result)); |
| 995 | 963 |
| 996 Label done, vfp_modulo, both_positive, right_negative; | 964 Label done, vfp_modulo, both_positive, right_negative; |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1179 } | 1147 } |
| 1180 } | 1148 } |
| 1181 | 1149 |
| 1182 | 1150 |
| 1183 void LCodeGen::DoDivI(LDivI* instr) { | 1151 void LCodeGen::DoDivI(LDivI* instr) { |
| 1184 class DeferredDivI: public LDeferredCode { | 1152 class DeferredDivI: public LDeferredCode { |
| 1185 public: | 1153 public: |
| 1186 DeferredDivI(LCodeGen* codegen, LDivI* instr) | 1154 DeferredDivI(LCodeGen* codegen, LDivI* instr) |
| 1187 : LDeferredCode(codegen), instr_(instr) { } | 1155 : LDeferredCode(codegen), instr_(instr) { } |
| 1188 virtual void Generate() { | 1156 virtual void Generate() { |
| 1189 codegen()->DoDeferredBinaryOpStub(instr_->pointer_map(), | 1157 codegen()->DoDeferredBinaryOpStub(instr_, Token::DIV); |
| 1190 instr_->left(), | |
| 1191 instr_->right(), | |
| 1192 Token::DIV); | |
| 1193 } | 1158 } |
| 1194 virtual LInstruction* instr() { return instr_; } | 1159 virtual LInstruction* instr() { return instr_; } |
| 1195 private: | 1160 private: |
| 1196 LDivI* instr_; | 1161 LDivI* instr_; |
| 1197 }; | 1162 }; |
| 1198 | 1163 |
| 1199 const Register left = ToRegister(instr->left()); | 1164 const Register left = ToRegister(instr->InputAt(0)); |
| 1200 const Register right = ToRegister(instr->right()); | 1165 const Register right = ToRegister(instr->InputAt(1)); |
| 1201 const Register scratch = scratch0(); | 1166 const Register scratch = scratch0(); |
| 1202 const Register result = ToRegister(instr->result()); | 1167 const Register result = ToRegister(instr->result()); |
| 1203 | 1168 |
| 1204 // Check for x / 0. | 1169 // Check for x / 0. |
| 1205 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1170 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1206 __ cmp(right, Operand(0)); | 1171 __ cmp(right, Operand(0)); |
| 1207 DeoptimizeIf(eq, instr->environment()); | 1172 DeoptimizeIf(eq, instr->environment()); |
| 1208 } | 1173 } |
| 1209 | 1174 |
| 1210 // Check for (0 / -x) that will produce negative zero. | 1175 // Check for (0 / -x) that will produce negative zero. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 __ b(&done); | 1224 __ b(&done); |
| 1260 | 1225 |
| 1261 __ bind(&deoptimize); | 1226 __ bind(&deoptimize); |
| 1262 DeoptimizeIf(al, instr->environment()); | 1227 DeoptimizeIf(al, instr->environment()); |
| 1263 __ bind(&done); | 1228 __ bind(&done); |
| 1264 } | 1229 } |
| 1265 | 1230 |
| 1266 | 1231 |
| 1267 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { | 1232 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { |
| 1268 const Register result = ToRegister(instr->result()); | 1233 const Register result = ToRegister(instr->result()); |
| 1269 const Register left = ToRegister(instr->left()); | 1234 const Register left = ToRegister(instr->InputAt(0)); |
| 1270 const Register remainder = ToRegister(instr->temp()); | 1235 const Register remainder = ToRegister(instr->TempAt(0)); |
| 1271 const Register scratch = scratch0(); | 1236 const Register scratch = scratch0(); |
| 1272 | 1237 |
| 1273 // We only optimize this for division by constants, because the standard | 1238 // We only optimize this for division by constants, because the standard |
| 1274 // integer division routine is usually slower than transitionning to VFP. | 1239 // integer division routine is usually slower than transitionning to VFP. |
| 1275 // This could be optimized on processors with SDIV available. | 1240 // This could be optimized on processors with SDIV available. |
| 1276 ASSERT(instr->right()->IsConstantOperand()); | 1241 ASSERT(instr->InputAt(1)->IsConstantOperand()); |
| 1277 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); | 1242 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->InputAt(1))); |
| 1278 if (divisor < 0) { | 1243 if (divisor < 0) { |
| 1279 __ cmp(left, Operand(0)); | 1244 __ cmp(left, Operand(0)); |
| 1280 DeoptimizeIf(eq, instr->environment()); | 1245 DeoptimizeIf(eq, instr->environment()); |
| 1281 } | 1246 } |
| 1282 EmitSignedIntegerDivisionByConstant(result, | 1247 EmitSignedIntegerDivisionByConstant(result, |
| 1283 left, | 1248 left, |
| 1284 divisor, | 1249 divisor, |
| 1285 remainder, | 1250 remainder, |
| 1286 scratch, | 1251 scratch, |
| 1287 instr->environment()); | 1252 instr->environment()); |
| 1288 // We operated a truncating division. Correct the result if necessary. | 1253 // We operated a truncating division. Correct the result if necessary. |
| 1289 __ cmp(remainder, Operand(0)); | 1254 __ cmp(remainder, Operand(0)); |
| 1290 __ teq(remainder, Operand(divisor), ne); | 1255 __ teq(remainder, Operand(divisor), ne); |
| 1291 __ sub(result, result, Operand(1), LeaveCC, mi); | 1256 __ sub(result, result, Operand(1), LeaveCC, mi); |
| 1292 } | 1257 } |
| 1293 | 1258 |
| 1294 | 1259 |
| 1295 void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map, | 1260 template<int T> |
| 1296 LOperand* left_argument, | 1261 void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, |
| 1297 LOperand* right_argument, | |
| 1298 Token::Value op) { | 1262 Token::Value op) { |
| 1299 Register left = ToRegister(left_argument); | 1263 Register left = ToRegister(instr->InputAt(0)); |
| 1300 Register right = ToRegister(right_argument); | 1264 Register right = ToRegister(instr->InputAt(1)); |
| 1301 | 1265 |
| 1302 PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); | 1266 PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); |
| 1303 // Move left to r1 and right to r0 for the stub call. | 1267 // Move left to r1 and right to r0 for the stub call. |
| 1304 if (left.is(r1)) { | 1268 if (left.is(r1)) { |
| 1305 __ Move(r0, right); | 1269 __ Move(r0, right); |
| 1306 } else if (left.is(r0) && right.is(r1)) { | 1270 } else if (left.is(r0) && right.is(r1)) { |
| 1307 __ Swap(r0, r1, r2); | 1271 __ Swap(r0, r1, r2); |
| 1308 } else if (left.is(r0)) { | 1272 } else if (left.is(r0)) { |
| 1309 ASSERT(!right.is(r1)); | 1273 ASSERT(!right.is(r1)); |
| 1310 __ mov(r1, r0); | 1274 __ mov(r1, r0); |
| 1311 __ mov(r0, right); | 1275 __ mov(r0, right); |
| 1312 } else { | 1276 } else { |
| 1313 ASSERT(!left.is(r0) && !right.is(r0)); | 1277 ASSERT(!left.is(r0) && !right.is(r0)); |
| 1314 __ mov(r0, right); | 1278 __ mov(r0, right); |
| 1315 __ mov(r1, left); | 1279 __ mov(r1, left); |
| 1316 } | 1280 } |
| 1317 BinaryOpStub stub(op, OVERWRITE_LEFT); | 1281 BinaryOpStub stub(op, OVERWRITE_LEFT); |
| 1318 __ CallStub(&stub); | 1282 __ CallStub(&stub); |
| 1319 RecordSafepointWithRegistersAndDoubles(pointer_map, | 1283 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
| 1320 0, | 1284 0, |
| 1321 Safepoint::kNoLazyDeopt); | 1285 Safepoint::kNoLazyDeopt); |
| 1322 // Overwrite the stored value of r0 with the result of the stub. | 1286 // Overwrite the stored value of r0 with the result of the stub. |
| 1323 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1287 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
| 1324 } | 1288 } |
| 1325 | 1289 |
| 1326 | 1290 |
| 1327 void LCodeGen::DoMulI(LMulI* instr) { | 1291 void LCodeGen::DoMulI(LMulI* instr) { |
| 1328 Register scratch = scratch0(); | 1292 Register scratch = scratch0(); |
| 1329 Register result = ToRegister(instr->result()); | 1293 Register result = ToRegister(instr->result()); |
| 1330 // Note that result may alias left. | 1294 // Note that result may alias left. |
| 1331 Register left = ToRegister(instr->left()); | 1295 Register left = ToRegister(instr->InputAt(0)); |
| 1332 LOperand* right_op = instr->right(); | 1296 LOperand* right_op = instr->InputAt(1); |
| 1333 | 1297 |
| 1334 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1298 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1335 bool bailout_on_minus_zero = | 1299 bool bailout_on_minus_zero = |
| 1336 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1300 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
| 1337 | 1301 |
| 1338 if (right_op->IsConstantOperand() && !can_overflow) { | 1302 if (right_op->IsConstantOperand() && !can_overflow) { |
| 1339 // Use optimized code for specific constants. | 1303 // Use optimized code for specific constants. |
| 1340 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1304 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
| 1341 | 1305 |
| 1342 if (bailout_on_minus_zero && (constant < 0)) { | 1306 if (bailout_on_minus_zero && (constant < 0)) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1389 } else { | 1353 } else { |
| 1390 // Generate standard code. | 1354 // Generate standard code. |
| 1391 __ mov(ip, Operand(constant)); | 1355 __ mov(ip, Operand(constant)); |
| 1392 __ mul(result, left, ip); | 1356 __ mul(result, left, ip); |
| 1393 } | 1357 } |
| 1394 } | 1358 } |
| 1395 | 1359 |
| 1396 } else { | 1360 } else { |
| 1397 Register right = EmitLoadRegister(right_op, scratch); | 1361 Register right = EmitLoadRegister(right_op, scratch); |
| 1398 if (bailout_on_minus_zero) { | 1362 if (bailout_on_minus_zero) { |
| 1399 __ orr(ToRegister(instr->temp()), left, right); | 1363 __ orr(ToRegister(instr->TempAt(0)), left, right); |
| 1400 } | 1364 } |
| 1401 | 1365 |
| 1402 if (can_overflow) { | 1366 if (can_overflow) { |
| 1403 // scratch:result = left * right. | 1367 // scratch:result = left * right. |
| 1404 __ smull(result, scratch, left, right); | 1368 __ smull(result, scratch, left, right); |
| 1405 __ cmp(scratch, Operand(result, ASR, 31)); | 1369 __ cmp(scratch, Operand(result, ASR, 31)); |
| 1406 DeoptimizeIf(ne, instr->environment()); | 1370 DeoptimizeIf(ne, instr->environment()); |
| 1407 } else { | 1371 } else { |
| 1408 __ mul(result, left, right); | 1372 __ mul(result, left, right); |
| 1409 } | 1373 } |
| 1410 | 1374 |
| 1411 if (bailout_on_minus_zero) { | 1375 if (bailout_on_minus_zero) { |
| 1412 // Bail out if the result is supposed to be negative zero. | 1376 // Bail out if the result is supposed to be negative zero. |
| 1413 Label done; | 1377 Label done; |
| 1414 __ cmp(result, Operand(0)); | 1378 __ cmp(result, Operand(0)); |
| 1415 __ b(ne, &done); | 1379 __ b(ne, &done); |
| 1416 __ cmp(ToRegister(instr->temp()), Operand(0)); | 1380 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); |
| 1417 DeoptimizeIf(mi, instr->environment()); | 1381 DeoptimizeIf(mi, instr->environment()); |
| 1418 __ bind(&done); | 1382 __ bind(&done); |
| 1419 } | 1383 } |
| 1420 } | 1384 } |
| 1421 } | 1385 } |
| 1422 | 1386 |
| 1423 | 1387 |
| 1424 void LCodeGen::DoBitI(LBitI* instr) { | 1388 void LCodeGen::DoBitI(LBitI* instr) { |
| 1425 LOperand* left_op = instr->left(); | 1389 LOperand* left_op = instr->InputAt(0); |
| 1426 LOperand* right_op = instr->right(); | 1390 LOperand* right_op = instr->InputAt(1); |
| 1427 ASSERT(left_op->IsRegister()); | 1391 ASSERT(left_op->IsRegister()); |
| 1428 Register left = ToRegister(left_op); | 1392 Register left = ToRegister(left_op); |
| 1429 Register result = ToRegister(instr->result()); | 1393 Register result = ToRegister(instr->result()); |
| 1430 Operand right(no_reg); | 1394 Operand right(no_reg); |
| 1431 | 1395 |
| 1432 if (right_op->IsStackSlot() || right_op->IsArgument()) { | 1396 if (right_op->IsStackSlot() || right_op->IsArgument()) { |
| 1433 right = Operand(EmitLoadRegister(right_op, ip)); | 1397 right = Operand(EmitLoadRegister(right_op, ip)); |
| 1434 } else { | 1398 } else { |
| 1435 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); | 1399 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); |
| 1436 right = ToOperand(right_op); | 1400 right = ToOperand(right_op); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1449 default: | 1413 default: |
| 1450 UNREACHABLE(); | 1414 UNREACHABLE(); |
| 1451 break; | 1415 break; |
| 1452 } | 1416 } |
| 1453 } | 1417 } |
| 1454 | 1418 |
| 1455 | 1419 |
| 1456 void LCodeGen::DoShiftI(LShiftI* instr) { | 1420 void LCodeGen::DoShiftI(LShiftI* instr) { |
| 1457 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so | 1421 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so |
| 1458 // result may alias either of them. | 1422 // result may alias either of them. |
| 1459 LOperand* right_op = instr->right(); | 1423 LOperand* right_op = instr->InputAt(1); |
| 1460 Register left = ToRegister(instr->left()); | 1424 Register left = ToRegister(instr->InputAt(0)); |
| 1461 Register result = ToRegister(instr->result()); | 1425 Register result = ToRegister(instr->result()); |
| 1462 Register scratch = scratch0(); | 1426 Register scratch = scratch0(); |
| 1463 if (right_op->IsRegister()) { | 1427 if (right_op->IsRegister()) { |
| 1464 // Mask the right_op operand. | 1428 // Mask the right_op operand. |
| 1465 __ and_(scratch, ToRegister(right_op), Operand(0x1F)); | 1429 __ and_(scratch, ToRegister(right_op), Operand(0x1F)); |
| 1466 switch (instr->op()) { | 1430 switch (instr->op()) { |
| 1467 case Token::SAR: | 1431 case Token::SAR: |
| 1468 __ mov(result, Operand(left, ASR, scratch)); | 1432 __ mov(result, Operand(left, ASR, scratch)); |
| 1469 break; | 1433 break; |
| 1470 case Token::SHR: | 1434 case Token::SHR: |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1514 break; | 1478 break; |
| 1515 default: | 1479 default: |
| 1516 UNREACHABLE(); | 1480 UNREACHABLE(); |
| 1517 break; | 1481 break; |
| 1518 } | 1482 } |
| 1519 } | 1483 } |
| 1520 } | 1484 } |
| 1521 | 1485 |
| 1522 | 1486 |
| 1523 void LCodeGen::DoSubI(LSubI* instr) { | 1487 void LCodeGen::DoSubI(LSubI* instr) { |
| 1524 LOperand* left = instr->left(); | 1488 LOperand* left = instr->InputAt(0); |
| 1525 LOperand* right = instr->right(); | 1489 LOperand* right = instr->InputAt(1); |
| 1526 LOperand* result = instr->result(); | 1490 LOperand* result = instr->result(); |
| 1527 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1491 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1528 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1492 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
| 1529 | 1493 |
| 1530 if (right->IsStackSlot() || right->IsArgument()) { | 1494 if (right->IsStackSlot() || right->IsArgument()) { |
| 1531 Register right_reg = EmitLoadRegister(right, ip); | 1495 Register right_reg = EmitLoadRegister(right, ip); |
| 1532 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 1496 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
| 1533 } else { | 1497 } else { |
| 1534 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1498 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
| 1535 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); | 1499 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
| 1536 } | 1500 } |
| 1537 | 1501 |
| 1538 if (can_overflow) { | 1502 if (can_overflow) { |
| 1539 DeoptimizeIf(vs, instr->environment()); | 1503 DeoptimizeIf(vs, instr->environment()); |
| 1540 } | 1504 } |
| 1541 } | 1505 } |
| 1542 | 1506 |
| 1543 | 1507 |
| 1544 void LCodeGen::DoConstantI(LConstantI* instr) { | 1508 void LCodeGen::DoConstantI(LConstantI* instr) { |
| 1545 ASSERT(instr->result()->IsRegister()); | 1509 ASSERT(instr->result()->IsRegister()); |
| 1546 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1510 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
| 1547 } | 1511 } |
| 1548 | 1512 |
| 1549 | 1513 |
| 1550 void LCodeGen::DoConstantD(LConstantD* instr) { | 1514 void LCodeGen::DoConstantD(LConstantD* instr) { |
| 1551 ASSERT(instr->result()->IsDoubleRegister()); | 1515 ASSERT(instr->result()->IsDoubleRegister()); |
| 1552 DwVfpRegister result = ToDoubleRegister(instr->result()); | 1516 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 1553 double v = instr->value(); | 1517 double v = instr->value(); |
| 1554 __ Vmov(result, v, scratch0()); | 1518 __ Vmov(result, v); |
| 1555 } | 1519 } |
| 1556 | 1520 |
| 1557 | 1521 |
| 1558 void LCodeGen::DoConstantT(LConstantT* instr) { | 1522 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 1559 Handle<Object> value = instr->value(); | 1523 Handle<Object> value = instr->value(); |
| 1560 if (value->IsSmi()) { | 1524 if (value->IsSmi()) { |
| 1561 __ mov(ToRegister(instr->result()), Operand(value)); | 1525 __ mov(ToRegister(instr->result()), Operand(value)); |
| 1562 } else { | 1526 } else { |
| 1563 __ LoadHeapObject(ToRegister(instr->result()), | 1527 __ LoadHeapObject(ToRegister(instr->result()), |
| 1564 Handle<HeapObject>::cast(value)); | 1528 Handle<HeapObject>::cast(value)); |
| 1565 } | 1529 } |
| 1566 } | 1530 } |
| 1567 | 1531 |
| 1568 | 1532 |
| 1569 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1533 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| 1570 Register result = ToRegister(instr->result()); | 1534 Register result = ToRegister(instr->result()); |
| 1571 Register array = ToRegister(instr->value()); | 1535 Register array = ToRegister(instr->InputAt(0)); |
| 1572 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); | 1536 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); |
| 1573 } | 1537 } |
| 1574 | 1538 |
| 1575 | 1539 |
| 1576 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { | 1540 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { |
| 1577 Register result = ToRegister(instr->result()); | 1541 Register result = ToRegister(instr->result()); |
| 1578 Register array = ToRegister(instr->value()); | 1542 Register array = ToRegister(instr->InputAt(0)); |
| 1579 __ ldr(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset)); | 1543 __ ldr(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset)); |
| 1580 } | 1544 } |
| 1581 | 1545 |
| 1582 | 1546 |
| 1583 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1547 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
| 1584 Register result = ToRegister(instr->result()); | 1548 Register result = ToRegister(instr->result()); |
| 1585 Register map = ToRegister(instr->value()); | 1549 Register map = ToRegister(instr->InputAt(0)); |
| 1586 __ EnumLength(result, map); | 1550 __ EnumLength(result, map); |
| 1587 } | 1551 } |
| 1588 | 1552 |
| 1589 | 1553 |
| 1590 void LCodeGen::DoElementsKind(LElementsKind* instr) { | 1554 void LCodeGen::DoElementsKind(LElementsKind* instr) { |
| 1591 Register result = ToRegister(instr->result()); | 1555 Register result = ToRegister(instr->result()); |
| 1592 Register input = ToRegister(instr->value()); | 1556 Register input = ToRegister(instr->InputAt(0)); |
| 1593 | 1557 |
| 1594 // Load map into |result|. | 1558 // Load map into |result|. |
| 1595 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); | 1559 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 1596 // Load the map's "bit field 2" into |result|. We only need the first byte, | 1560 // Load the map's "bit field 2" into |result|. We only need the first byte, |
| 1597 // but the following bit field extraction takes care of that anyway. | 1561 // but the following bit field extraction takes care of that anyway. |
| 1598 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset)); | 1562 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset)); |
| 1599 // Retrieve elements_kind from bit field 2. | 1563 // Retrieve elements_kind from bit field 2. |
| 1600 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); | 1564 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); |
| 1601 } | 1565 } |
| 1602 | 1566 |
| 1603 | 1567 |
| 1604 void LCodeGen::DoValueOf(LValueOf* instr) { | 1568 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 1605 Register input = ToRegister(instr->value()); | 1569 Register input = ToRegister(instr->InputAt(0)); |
| 1606 Register result = ToRegister(instr->result()); | 1570 Register result = ToRegister(instr->result()); |
| 1607 Register map = ToRegister(instr->temp()); | 1571 Register map = ToRegister(instr->TempAt(0)); |
| 1608 Label done; | 1572 Label done; |
| 1609 | 1573 |
| 1610 // If the object is a smi return the object. | 1574 // If the object is a smi return the object. |
| 1611 __ tst(input, Operand(kSmiTagMask)); | 1575 __ tst(input, Operand(kSmiTagMask)); |
| 1612 __ Move(result, input, eq); | 1576 __ Move(result, input, eq); |
| 1613 __ b(eq, &done); | 1577 __ b(eq, &done); |
| 1614 | 1578 |
| 1615 // If the object is not a value type, return the object. | 1579 // If the object is not a value type, return the object. |
| 1616 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); | 1580 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); |
| 1617 __ Move(result, input, ne); | 1581 __ Move(result, input, ne); |
| 1618 __ b(ne, &done); | 1582 __ b(ne, &done); |
| 1619 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); | 1583 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); |
| 1620 | 1584 |
| 1621 __ bind(&done); | 1585 __ bind(&done); |
| 1622 } | 1586 } |
| 1623 | 1587 |
| 1624 | 1588 |
| 1625 void LCodeGen::DoDateField(LDateField* instr) { | 1589 void LCodeGen::DoDateField(LDateField* instr) { |
| 1626 Register object = ToRegister(instr->date()); | 1590 Register object = ToRegister(instr->InputAt(0)); |
| 1627 Register result = ToRegister(instr->result()); | 1591 Register result = ToRegister(instr->result()); |
| 1628 Register scratch = ToRegister(instr->temp()); | 1592 Register scratch = ToRegister(instr->TempAt(0)); |
| 1629 Smi* index = instr->index(); | 1593 Smi* index = instr->index(); |
| 1630 Label runtime, done; | 1594 Label runtime, done; |
| 1631 ASSERT(object.is(result)); | 1595 ASSERT(object.is(result)); |
| 1632 ASSERT(object.is(r0)); | 1596 ASSERT(object.is(r0)); |
| 1633 ASSERT(!scratch.is(scratch0())); | 1597 ASSERT(!scratch.is(scratch0())); |
| 1634 ASSERT(!scratch.is(object)); | 1598 ASSERT(!scratch.is(object)); |
| 1635 | 1599 |
| 1636 __ tst(object, Operand(kSmiTagMask)); | 1600 __ tst(object, Operand(kSmiTagMask)); |
| 1637 DeoptimizeIf(eq, instr->environment()); | 1601 DeoptimizeIf(eq, instr->environment()); |
| 1638 __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE); | 1602 __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1655 __ bind(&runtime); | 1619 __ bind(&runtime); |
| 1656 __ PrepareCallCFunction(2, scratch); | 1620 __ PrepareCallCFunction(2, scratch); |
| 1657 __ mov(r1, Operand(index)); | 1621 __ mov(r1, Operand(index)); |
| 1658 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 1622 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 1659 __ bind(&done); | 1623 __ bind(&done); |
| 1660 } | 1624 } |
| 1661 } | 1625 } |
| 1662 | 1626 |
| 1663 | 1627 |
| 1664 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1628 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 1665 Register input = ToRegister(instr->value()); | 1629 Register input = ToRegister(instr->InputAt(0)); |
| 1666 Register result = ToRegister(instr->result()); | 1630 Register result = ToRegister(instr->result()); |
| 1667 __ mvn(result, Operand(input)); | 1631 __ mvn(result, Operand(input)); |
| 1668 } | 1632 } |
| 1669 | 1633 |
| 1670 | 1634 |
| 1671 void LCodeGen::DoThrow(LThrow* instr) { | 1635 void LCodeGen::DoThrow(LThrow* instr) { |
| 1672 Register input_reg = EmitLoadRegister(instr->value(), ip); | 1636 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
| 1673 __ push(input_reg); | 1637 __ push(input_reg); |
| 1674 CallRuntime(Runtime::kThrow, 1, instr); | 1638 CallRuntime(Runtime::kThrow, 1, instr); |
| 1675 | 1639 |
| 1676 if (FLAG_debug_code) { | 1640 if (FLAG_debug_code) { |
| 1677 __ stop("Unreachable code."); | 1641 __ stop("Unreachable code."); |
| 1678 } | 1642 } |
| 1679 } | 1643 } |
| 1680 | 1644 |
| 1681 | 1645 |
| 1682 void LCodeGen::DoAddI(LAddI* instr) { | 1646 void LCodeGen::DoAddI(LAddI* instr) { |
| 1683 LOperand* left = instr->left(); | 1647 LOperand* left = instr->InputAt(0); |
| 1684 LOperand* right = instr->right(); | 1648 LOperand* right = instr->InputAt(1); |
| 1685 LOperand* result = instr->result(); | 1649 LOperand* result = instr->result(); |
| 1686 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1650 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1687 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1651 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
| 1688 | 1652 |
| 1689 if (right->IsStackSlot() || right->IsArgument()) { | 1653 if (right->IsStackSlot() || right->IsArgument()) { |
| 1690 Register right_reg = EmitLoadRegister(right, ip); | 1654 Register right_reg = EmitLoadRegister(right, ip); |
| 1691 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 1655 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
| 1692 } else { | 1656 } else { |
| 1693 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1657 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
| 1694 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); | 1658 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
| 1695 } | 1659 } |
| 1696 | 1660 |
| 1697 if (can_overflow) { | 1661 if (can_overflow) { |
| 1698 DeoptimizeIf(vs, instr->environment()); | 1662 DeoptimizeIf(vs, instr->environment()); |
| 1699 } | 1663 } |
| 1700 } | 1664 } |
| 1701 | 1665 |
| 1702 | 1666 |
| 1703 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1667 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
| 1704 LOperand* left = instr->left(); | 1668 LOperand* left = instr->InputAt(0); |
| 1705 LOperand* right = instr->right(); | 1669 LOperand* right = instr->InputAt(1); |
| 1706 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1670 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
| 1707 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | 1671 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; |
| 1708 if (instr->hydrogen()->representation().IsInteger32()) { | 1672 if (instr->hydrogen()->representation().IsInteger32()) { |
| 1709 Register left_reg = ToRegister(left); | 1673 Register left_reg = ToRegister(left); |
| 1710 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) | 1674 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) |
| 1711 ? ToOperand(right) | 1675 ? ToOperand(right) |
| 1712 : Operand(EmitLoadRegister(right, ip)); | 1676 : Operand(EmitLoadRegister(right, ip)); |
| 1713 Register result_reg = ToRegister(instr->result()); | 1677 Register result_reg = ToRegister(instr->result()); |
| 1714 __ cmp(left_reg, right_op); | 1678 __ cmp(left_reg, right_op); |
| 1715 if (!result_reg.is(left_reg)) { | 1679 if (!result_reg.is(left_reg)) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1756 __ bind(&return_left); | 1720 __ bind(&return_left); |
| 1757 if (!left_reg.is(result_reg)) { | 1721 if (!left_reg.is(result_reg)) { |
| 1758 __ vmov(result_reg, left_reg); | 1722 __ vmov(result_reg, left_reg); |
| 1759 } | 1723 } |
| 1760 __ bind(&done); | 1724 __ bind(&done); |
| 1761 } | 1725 } |
| 1762 } | 1726 } |
| 1763 | 1727 |
| 1764 | 1728 |
| 1765 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1729 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 1766 DoubleRegister left = ToDoubleRegister(instr->left()); | 1730 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); |
| 1767 DoubleRegister right = ToDoubleRegister(instr->right()); | 1731 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); |
| 1768 DoubleRegister result = ToDoubleRegister(instr->result()); | 1732 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 1769 switch (instr->op()) { | 1733 switch (instr->op()) { |
| 1770 case Token::ADD: | 1734 case Token::ADD: |
| 1771 __ vadd(result, left, right); | 1735 __ vadd(result, left, right); |
| 1772 break; | 1736 break; |
| 1773 case Token::SUB: | 1737 case Token::SUB: |
| 1774 __ vsub(result, left, right); | 1738 __ vsub(result, left, right); |
| 1775 break; | 1739 break; |
| 1776 case Token::MUL: | 1740 case Token::MUL: |
| 1777 __ vmul(result, left, right); | 1741 __ vmul(result, left, right); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1796 break; | 1760 break; |
| 1797 } | 1761 } |
| 1798 default: | 1762 default: |
| 1799 UNREACHABLE(); | 1763 UNREACHABLE(); |
| 1800 break; | 1764 break; |
| 1801 } | 1765 } |
| 1802 } | 1766 } |
| 1803 | 1767 |
| 1804 | 1768 |
| 1805 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1769 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1806 ASSERT(ToRegister(instr->left()).is(r1)); | 1770 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); |
| 1807 ASSERT(ToRegister(instr->right()).is(r0)); | 1771 ASSERT(ToRegister(instr->InputAt(1)).is(r0)); |
| 1808 ASSERT(ToRegister(instr->result()).is(r0)); | 1772 ASSERT(ToRegister(instr->result()).is(r0)); |
| 1809 | 1773 |
| 1810 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1774 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1811 // Block literal pool emission to ensure nop indicating no inlined smi code | 1775 // Block literal pool emission to ensure nop indicating no inlined smi code |
| 1812 // is in the correct position. | 1776 // is in the correct position. |
| 1813 Assembler::BlockConstPoolScope block_const_pool(masm()); | 1777 Assembler::BlockConstPoolScope block_const_pool(masm()); |
| 1814 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1778 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1815 __ nop(); // Signals no inlined code. | 1779 __ nop(); // Signals no inlined code. |
| 1816 } | 1780 } |
| 1817 | 1781 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1842 } | 1806 } |
| 1843 } | 1807 } |
| 1844 | 1808 |
| 1845 | 1809 |
| 1846 void LCodeGen::DoBranch(LBranch* instr) { | 1810 void LCodeGen::DoBranch(LBranch* instr) { |
| 1847 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1811 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1848 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1812 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1849 | 1813 |
| 1850 Representation r = instr->hydrogen()->value()->representation(); | 1814 Representation r = instr->hydrogen()->value()->representation(); |
| 1851 if (r.IsInteger32()) { | 1815 if (r.IsInteger32()) { |
| 1852 Register reg = ToRegister(instr->value()); | 1816 Register reg = ToRegister(instr->InputAt(0)); |
| 1853 __ cmp(reg, Operand(0)); | 1817 __ cmp(reg, Operand(0)); |
| 1854 EmitBranch(true_block, false_block, ne); | 1818 EmitBranch(true_block, false_block, ne); |
| 1855 } else if (r.IsDouble()) { | 1819 } else if (r.IsDouble()) { |
| 1856 DoubleRegister reg = ToDoubleRegister(instr->value()); | 1820 DoubleRegister reg = ToDoubleRegister(instr->InputAt(0)); |
| 1857 Register scratch = scratch0(); | 1821 Register scratch = scratch0(); |
| 1858 | 1822 |
| 1859 // Test the double value. Zero and NaN are false. | 1823 // Test the double value. Zero and NaN are false. |
| 1860 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); | 1824 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); |
| 1861 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 1825 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
| 1862 EmitBranch(true_block, false_block, eq); | 1826 EmitBranch(true_block, false_block, eq); |
| 1863 } else { | 1827 } else { |
| 1864 ASSERT(r.IsTagged()); | 1828 ASSERT(r.IsTagged()); |
| 1865 Register reg = ToRegister(instr->value()); | 1829 Register reg = ToRegister(instr->InputAt(0)); |
| 1866 HType type = instr->hydrogen()->value()->type(); | 1830 HType type = instr->hydrogen()->value()->type(); |
| 1867 if (type.IsBoolean()) { | 1831 if (type.IsBoolean()) { |
| 1868 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1832 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
| 1869 EmitBranch(true_block, false_block, eq); | 1833 EmitBranch(true_block, false_block, eq); |
| 1870 } else if (type.IsSmi()) { | 1834 } else if (type.IsSmi()) { |
| 1871 __ cmp(reg, Operand(0)); | 1835 __ cmp(reg, Operand(0)); |
| 1872 EmitBranch(true_block, false_block, ne); | 1836 EmitBranch(true_block, false_block, ne); |
| 1873 } else { | 1837 } else { |
| 1874 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1838 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1875 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1839 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1994 case Token::IN: | 1958 case Token::IN: |
| 1995 case Token::INSTANCEOF: | 1959 case Token::INSTANCEOF: |
| 1996 default: | 1960 default: |
| 1997 UNREACHABLE(); | 1961 UNREACHABLE(); |
| 1998 } | 1962 } |
| 1999 return cond; | 1963 return cond; |
| 2000 } | 1964 } |
| 2001 | 1965 |
| 2002 | 1966 |
| 2003 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1967 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
| 2004 LOperand* left = instr->left(); | 1968 LOperand* left = instr->InputAt(0); |
| 2005 LOperand* right = instr->right(); | 1969 LOperand* right = instr->InputAt(1); |
| 2006 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1970 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2007 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1971 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2008 Condition cond = TokenToCondition(instr->op(), false); | 1972 Condition cond = TokenToCondition(instr->op(), false); |
| 2009 | 1973 |
| 2010 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 1974 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
| 2011 // We can statically evaluate the comparison. | 1975 // We can statically evaluate the comparison. |
| 2012 double left_val = ToDouble(LConstantOperand::cast(left)); | 1976 double left_val = ToDouble(LConstantOperand::cast(left)); |
| 2013 double right_val = ToDouble(LConstantOperand::cast(right)); | 1977 double right_val = ToDouble(LConstantOperand::cast(right)); |
| 2014 int next_block = | 1978 int next_block = |
| 2015 EvalComparison(instr->op(), left_val, right_val) ? true_block | 1979 EvalComparison(instr->op(), left_val, right_val) ? true_block |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2035 } else { | 1999 } else { |
| 2036 __ cmp(ToRegister(left), ToRegister(right)); | 2000 __ cmp(ToRegister(left), ToRegister(right)); |
| 2037 } | 2001 } |
| 2038 } | 2002 } |
| 2039 EmitBranch(true_block, false_block, cond); | 2003 EmitBranch(true_block, false_block, cond); |
| 2040 } | 2004 } |
| 2041 } | 2005 } |
| 2042 | 2006 |
| 2043 | 2007 |
| 2044 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2008 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
| 2045 Register left = ToRegister(instr->left()); | 2009 Register left = ToRegister(instr->InputAt(0)); |
| 2046 Register right = ToRegister(instr->right()); | 2010 Register right = ToRegister(instr->InputAt(1)); |
| 2047 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2011 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2048 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2012 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2049 | 2013 |
| 2050 __ cmp(left, Operand(right)); | 2014 __ cmp(left, Operand(right)); |
| 2051 EmitBranch(true_block, false_block, eq); | 2015 EmitBranch(true_block, false_block, eq); |
| 2052 } | 2016 } |
| 2053 | 2017 |
| 2054 | 2018 |
| 2055 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 2019 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
| 2056 Register left = ToRegister(instr->left()); | 2020 Register left = ToRegister(instr->InputAt(0)); |
| 2057 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2021 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2058 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2022 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2059 | 2023 |
| 2060 __ cmp(left, Operand(instr->hydrogen()->right())); | 2024 __ cmp(left, Operand(instr->hydrogen()->right())); |
| 2061 EmitBranch(true_block, false_block, eq); | 2025 EmitBranch(true_block, false_block, eq); |
| 2062 } | 2026 } |
| 2063 | 2027 |
| 2064 | 2028 |
| 2065 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { | 2029 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { |
| 2066 Register scratch = scratch0(); | 2030 Register scratch = scratch0(); |
| 2067 Register reg = ToRegister(instr->value()); | 2031 Register reg = ToRegister(instr->InputAt(0)); |
| 2068 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2032 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2069 | 2033 |
| 2070 // If the expression is known to be untagged or a smi, then it's definitely | 2034 // If the expression is known to be untagged or a smi, then it's definitely |
| 2071 // not null, and it can't be a an undetectable object. | 2035 // not null, and it can't be a an undetectable object. |
| 2072 if (instr->hydrogen()->representation().IsSpecialization() || | 2036 if (instr->hydrogen()->representation().IsSpecialization() || |
| 2073 instr->hydrogen()->type().IsSmi()) { | 2037 instr->hydrogen()->type().IsSmi()) { |
| 2074 EmitGoto(false_block); | 2038 EmitGoto(false_block); |
| 2075 return; | 2039 return; |
| 2076 } | 2040 } |
| 2077 | 2041 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2125 // Load instance type and check that it is in object type range. | 2089 // Load instance type and check that it is in object type range. |
| 2126 __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset)); | 2090 __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset)); |
| 2127 __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2091 __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 2128 __ b(lt, is_not_object); | 2092 __ b(lt, is_not_object); |
| 2129 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2093 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 2130 return le; | 2094 return le; |
| 2131 } | 2095 } |
| 2132 | 2096 |
| 2133 | 2097 |
| 2134 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 2098 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
| 2135 Register reg = ToRegister(instr->value()); | 2099 Register reg = ToRegister(instr->InputAt(0)); |
| 2136 Register temp1 = ToRegister(instr->temp()); | 2100 Register temp1 = ToRegister(instr->TempAt(0)); |
| 2137 | 2101 |
| 2138 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2102 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2139 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2103 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2140 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2104 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 2141 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2105 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 2142 | 2106 |
| 2143 Condition true_cond = | 2107 Condition true_cond = |
| 2144 EmitIsObject(reg, temp1, false_label, true_label); | 2108 EmitIsObject(reg, temp1, false_label, true_label); |
| 2145 | 2109 |
| 2146 EmitBranch(true_block, false_block, true_cond); | 2110 EmitBranch(true_block, false_block, true_cond); |
| 2147 } | 2111 } |
| 2148 | 2112 |
| 2149 | 2113 |
| 2150 Condition LCodeGen::EmitIsString(Register input, | 2114 Condition LCodeGen::EmitIsString(Register input, |
| 2151 Register temp1, | 2115 Register temp1, |
| 2152 Label* is_not_string) { | 2116 Label* is_not_string) { |
| 2153 __ JumpIfSmi(input, is_not_string); | 2117 __ JumpIfSmi(input, is_not_string); |
| 2154 __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE); | 2118 __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE); |
| 2155 | 2119 |
| 2156 return lt; | 2120 return lt; |
| 2157 } | 2121 } |
| 2158 | 2122 |
| 2159 | 2123 |
| 2160 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 2124 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
| 2161 Register reg = ToRegister(instr->value()); | 2125 Register reg = ToRegister(instr->InputAt(0)); |
| 2162 Register temp1 = ToRegister(instr->temp()); | 2126 Register temp1 = ToRegister(instr->TempAt(0)); |
| 2163 | 2127 |
| 2164 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2128 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2165 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2129 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2166 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2130 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 2167 | 2131 |
| 2168 Condition true_cond = | 2132 Condition true_cond = |
| 2169 EmitIsString(reg, temp1, false_label); | 2133 EmitIsString(reg, temp1, false_label); |
| 2170 | 2134 |
| 2171 EmitBranch(true_block, false_block, true_cond); | 2135 EmitBranch(true_block, false_block, true_cond); |
| 2172 } | 2136 } |
| 2173 | 2137 |
| 2174 | 2138 |
| 2175 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 2139 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
| 2176 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2140 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2177 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2141 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2178 | 2142 |
| 2179 Register input_reg = EmitLoadRegister(instr->value(), ip); | 2143 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
| 2180 __ tst(input_reg, Operand(kSmiTagMask)); | 2144 __ tst(input_reg, Operand(kSmiTagMask)); |
| 2181 EmitBranch(true_block, false_block, eq); | 2145 EmitBranch(true_block, false_block, eq); |
| 2182 } | 2146 } |
| 2183 | 2147 |
| 2184 | 2148 |
| 2185 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 2149 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
| 2186 Register input = ToRegister(instr->value()); | 2150 Register input = ToRegister(instr->InputAt(0)); |
| 2187 Register temp = ToRegister(instr->temp()); | 2151 Register temp = ToRegister(instr->TempAt(0)); |
| 2188 | 2152 |
| 2189 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2153 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2190 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2154 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2191 | 2155 |
| 2192 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 2156 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); |
| 2193 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); | 2157 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 2194 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); | 2158 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); |
| 2195 __ tst(temp, Operand(1 << Map::kIsUndetectable)); | 2159 __ tst(temp, Operand(1 << Map::kIsUndetectable)); |
| 2196 EmitBranch(true_block, false_block, ne); | 2160 EmitBranch(true_block, false_block, ne); |
| 2197 } | 2161 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2247 if (from == to) return eq; | 2211 if (from == to) return eq; |
| 2248 if (to == LAST_TYPE) return hs; | 2212 if (to == LAST_TYPE) return hs; |
| 2249 if (from == FIRST_TYPE) return ls; | 2213 if (from == FIRST_TYPE) return ls; |
| 2250 UNREACHABLE(); | 2214 UNREACHABLE(); |
| 2251 return eq; | 2215 return eq; |
| 2252 } | 2216 } |
| 2253 | 2217 |
| 2254 | 2218 |
| 2255 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 2219 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 2256 Register scratch = scratch0(); | 2220 Register scratch = scratch0(); |
| 2257 Register input = ToRegister(instr->value()); | 2221 Register input = ToRegister(instr->InputAt(0)); |
| 2258 | 2222 |
| 2259 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2223 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2260 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2224 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2261 | 2225 |
| 2262 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2226 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 2263 | 2227 |
| 2264 __ JumpIfSmi(input, false_label); | 2228 __ JumpIfSmi(input, false_label); |
| 2265 | 2229 |
| 2266 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); | 2230 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); |
| 2267 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 2231 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
| 2268 } | 2232 } |
| 2269 | 2233 |
| 2270 | 2234 |
| 2271 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2235 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
| 2272 Register input = ToRegister(instr->value()); | 2236 Register input = ToRegister(instr->InputAt(0)); |
| 2273 Register result = ToRegister(instr->result()); | 2237 Register result = ToRegister(instr->result()); |
| 2274 | 2238 |
| 2275 __ AbortIfNotString(input); | 2239 __ AbortIfNotString(input); |
| 2276 | 2240 |
| 2277 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); | 2241 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); |
| 2278 __ IndexFromHash(result, result); | 2242 __ IndexFromHash(result, result); |
| 2279 } | 2243 } |
| 2280 | 2244 |
| 2281 | 2245 |
| 2282 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2246 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| 2283 LHasCachedArrayIndexAndBranch* instr) { | 2247 LHasCachedArrayIndexAndBranch* instr) { |
| 2284 Register input = ToRegister(instr->value()); | 2248 Register input = ToRegister(instr->InputAt(0)); |
| 2285 Register scratch = scratch0(); | 2249 Register scratch = scratch0(); |
| 2286 | 2250 |
| 2287 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2251 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2288 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2252 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2289 | 2253 |
| 2290 __ ldr(scratch, | 2254 __ ldr(scratch, |
| 2291 FieldMemOperand(input, String::kHashFieldOffset)); | 2255 FieldMemOperand(input, String::kHashFieldOffset)); |
| 2292 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); | 2256 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); |
| 2293 EmitBranch(true_block, false_block, eq); | 2257 EmitBranch(true_block, false_block, eq); |
| 2294 } | 2258 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2355 // booted. This routine isn't expected to work for random API-created | 2319 // booted. This routine isn't expected to work for random API-created |
| 2356 // classes and it doesn't have to because you can't access it with natives | 2320 // classes and it doesn't have to because you can't access it with natives |
| 2357 // syntax. Since both sides are symbols it is sufficient to use an identity | 2321 // syntax. Since both sides are symbols it is sufficient to use an identity |
| 2358 // comparison. | 2322 // comparison. |
| 2359 __ cmp(temp, Operand(class_name)); | 2323 __ cmp(temp, Operand(class_name)); |
| 2360 // End with the answer in flags. | 2324 // End with the answer in flags. |
| 2361 } | 2325 } |
| 2362 | 2326 |
| 2363 | 2327 |
| 2364 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2328 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 2365 Register input = ToRegister(instr->value()); | 2329 Register input = ToRegister(instr->InputAt(0)); |
| 2366 Register temp = scratch0(); | 2330 Register temp = scratch0(); |
| 2367 Register temp2 = ToRegister(instr->temp()); | 2331 Register temp2 = ToRegister(instr->TempAt(0)); |
| 2368 Handle<String> class_name = instr->hydrogen()->class_name(); | 2332 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 2369 | 2333 |
| 2370 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2334 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2371 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2335 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2372 | 2336 |
| 2373 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2337 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 2374 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2338 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 2375 | 2339 |
| 2376 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 2340 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
| 2377 | 2341 |
| 2378 EmitBranch(true_block, false_block, eq); | 2342 EmitBranch(true_block, false_block, eq); |
| 2379 } | 2343 } |
| 2380 | 2344 |
| 2381 | 2345 |
| 2382 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2346 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 2383 Register reg = ToRegister(instr->value()); | 2347 Register reg = ToRegister(instr->InputAt(0)); |
| 2384 Register temp = ToRegister(instr->temp()); | 2348 Register temp = ToRegister(instr->TempAt(0)); |
| 2385 int true_block = instr->true_block_id(); | 2349 int true_block = instr->true_block_id(); |
| 2386 int false_block = instr->false_block_id(); | 2350 int false_block = instr->false_block_id(); |
| 2387 | 2351 |
| 2388 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2352 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2389 __ cmp(temp, Operand(instr->map())); | 2353 __ cmp(temp, Operand(instr->map())); |
| 2390 EmitBranch(true_block, false_block, eq); | 2354 EmitBranch(true_block, false_block, eq); |
| 2391 } | 2355 } |
| 2392 | 2356 |
| 2393 | 2357 |
| 2394 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2358 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 2395 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. | 2359 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); // Object is in r0. |
| 2396 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. | 2360 ASSERT(ToRegister(instr->InputAt(1)).is(r1)); // Function is in r1. |
| 2397 | 2361 |
| 2398 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2362 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 2399 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2363 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2400 | 2364 |
| 2401 __ cmp(r0, Operand(0)); | 2365 __ cmp(r0, Operand(0)); |
| 2402 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); | 2366 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); |
| 2403 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); | 2367 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); |
| 2404 } | 2368 } |
| 2405 | 2369 |
| 2406 | 2370 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2417 Label* map_check() { return &map_check_; } | 2381 Label* map_check() { return &map_check_; } |
| 2418 private: | 2382 private: |
| 2419 LInstanceOfKnownGlobal* instr_; | 2383 LInstanceOfKnownGlobal* instr_; |
| 2420 Label map_check_; | 2384 Label map_check_; |
| 2421 }; | 2385 }; |
| 2422 | 2386 |
| 2423 DeferredInstanceOfKnownGlobal* deferred; | 2387 DeferredInstanceOfKnownGlobal* deferred; |
| 2424 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2388 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
| 2425 | 2389 |
| 2426 Label done, false_result; | 2390 Label done, false_result; |
| 2427 Register object = ToRegister(instr->value()); | 2391 Register object = ToRegister(instr->InputAt(0)); |
| 2428 Register temp = ToRegister(instr->temp()); | 2392 Register temp = ToRegister(instr->TempAt(0)); |
| 2429 Register result = ToRegister(instr->result()); | 2393 Register result = ToRegister(instr->result()); |
| 2430 | 2394 |
| 2431 ASSERT(object.is(r0)); | 2395 ASSERT(object.is(r0)); |
| 2432 ASSERT(result.is(r0)); | 2396 ASSERT(result.is(r0)); |
| 2433 | 2397 |
| 2434 // A Smi is not instance of anything. | 2398 // A Smi is not instance of anything. |
| 2435 __ JumpIfSmi(object, &false_result); | 2399 __ JumpIfSmi(object, &false_result); |
| 2436 | 2400 |
| 2437 // This is the inlined call site instanceof cache. The two occurences of the | 2401 // This is the inlined call site instanceof cache. The two occurences of the |
| 2438 // hole value will be patched to the last map/result pair generated by the | 2402 // hole value will be patched to the last map/result pair generated by the |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2498 flags | InstanceofStub::kCallSiteInlineCheck); | 2462 flags | InstanceofStub::kCallSiteInlineCheck); |
| 2499 flags = static_cast<InstanceofStub::Flags>( | 2463 flags = static_cast<InstanceofStub::Flags>( |
| 2500 flags | InstanceofStub::kReturnTrueFalseObject); | 2464 flags | InstanceofStub::kReturnTrueFalseObject); |
| 2501 InstanceofStub stub(flags); | 2465 InstanceofStub stub(flags); |
| 2502 | 2466 |
| 2503 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 2467 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 2504 | 2468 |
| 2505 // Get the temp register reserved by the instruction. This needs to be r4 as | 2469 // Get the temp register reserved by the instruction. This needs to be r4 as |
| 2506 // its slot of the pushing of safepoint registers is used to communicate the | 2470 // its slot of the pushing of safepoint registers is used to communicate the |
| 2507 // offset to the location of the map check. | 2471 // offset to the location of the map check. |
| 2508 Register temp = ToRegister(instr->temp()); | 2472 Register temp = ToRegister(instr->TempAt(0)); |
| 2509 ASSERT(temp.is(r4)); | 2473 ASSERT(temp.is(r4)); |
| 2510 __ LoadHeapObject(InstanceofStub::right(), instr->function()); | 2474 __ LoadHeapObject(InstanceofStub::right(), instr->function()); |
| 2511 static const int kAdditionalDelta = 5; | 2475 static const int kAdditionalDelta = 5; |
| 2512 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; | 2476 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; |
| 2513 Label before_push_delta; | 2477 Label before_push_delta; |
| 2514 __ bind(&before_push_delta); | 2478 __ bind(&before_push_delta); |
| 2515 __ BlockConstPoolFor(kAdditionalDelta); | 2479 __ BlockConstPoolFor(kAdditionalDelta); |
| 2516 __ mov(temp, Operand(delta * kPointerSize)); | 2480 __ mov(temp, Operand(delta * kPointerSize)); |
| 2517 // The mov above can generate one or two instructions. The delta was computed | 2481 // The mov above can generate one or two instructions. The delta was computed |
| 2518 // for two instructions, so we need to pad here in case of one instruction. | 2482 // for two instructions, so we need to pad here in case of one instruction. |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2595 | 2559 |
| 2596 // Load the cell. | 2560 // Load the cell. |
| 2597 __ mov(cell, Operand(instr->hydrogen()->cell())); | 2561 __ mov(cell, Operand(instr->hydrogen()->cell())); |
| 2598 | 2562 |
| 2599 // If the cell we are storing to contains the hole it could have | 2563 // If the cell we are storing to contains the hole it could have |
| 2600 // been deleted from the property dictionary. In that case, we need | 2564 // been deleted from the property dictionary. In that case, we need |
| 2601 // to update the property details in the property dictionary to mark | 2565 // to update the property details in the property dictionary to mark |
| 2602 // it as no longer deleted. | 2566 // it as no longer deleted. |
| 2603 if (instr->hydrogen()->RequiresHoleCheck()) { | 2567 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2604 // We use a temp to check the payload (CompareRoot might clobber ip). | 2568 // We use a temp to check the payload (CompareRoot might clobber ip). |
| 2605 Register payload = ToRegister(instr->temp()); | 2569 Register payload = ToRegister(instr->TempAt(0)); |
| 2606 __ ldr(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); | 2570 __ ldr(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); |
| 2607 __ CompareRoot(payload, Heap::kTheHoleValueRootIndex); | 2571 __ CompareRoot(payload, Heap::kTheHoleValueRootIndex); |
| 2608 DeoptimizeIf(eq, instr->environment()); | 2572 DeoptimizeIf(eq, instr->environment()); |
| 2609 } | 2573 } |
| 2610 | 2574 |
| 2611 // Store the value. | 2575 // Store the value. |
| 2612 __ str(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); | 2576 __ str(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); |
| 2613 // Cells are always rescanned, so no write barrier here. | 2577 // Cells are always rescanned, so no write barrier here. |
| 2614 } | 2578 } |
| 2615 | 2579 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2674 kSaveFPRegs, | 2638 kSaveFPRegs, |
| 2675 EMIT_REMEMBERED_SET, | 2639 EMIT_REMEMBERED_SET, |
| 2676 check_needed); | 2640 check_needed); |
| 2677 } | 2641 } |
| 2678 | 2642 |
| 2679 __ bind(&skip_assignment); | 2643 __ bind(&skip_assignment); |
| 2680 } | 2644 } |
| 2681 | 2645 |
| 2682 | 2646 |
| 2683 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2647 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 2684 Register object = ToRegister(instr->object()); | 2648 Register object = ToRegister(instr->InputAt(0)); |
| 2685 Register result = ToRegister(instr->result()); | 2649 Register result = ToRegister(instr->result()); |
| 2686 if (instr->hydrogen()->is_in_object()) { | 2650 if (instr->hydrogen()->is_in_object()) { |
| 2687 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); | 2651 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); |
| 2688 } else { | 2652 } else { |
| 2689 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 2653 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 2690 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); | 2654 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); |
| 2691 } | 2655 } |
| 2692 } | 2656 } |
| 2693 | 2657 |
| 2694 | 2658 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2828 __ bind(&non_instance); | 2792 __ bind(&non_instance); |
| 2829 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); | 2793 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); |
| 2830 | 2794 |
| 2831 // All done. | 2795 // All done. |
| 2832 __ bind(&done); | 2796 __ bind(&done); |
| 2833 } | 2797 } |
| 2834 | 2798 |
| 2835 | 2799 |
| 2836 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2800 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
| 2837 Register result = ToRegister(instr->result()); | 2801 Register result = ToRegister(instr->result()); |
| 2838 Register input = ToRegister(instr->object()); | 2802 Register input = ToRegister(instr->InputAt(0)); |
| 2839 Register scratch = scratch0(); | 2803 Register scratch = scratch0(); |
| 2840 | 2804 |
| 2841 __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset)); | 2805 __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset)); |
| 2842 if (FLAG_debug_code) { | 2806 if (FLAG_debug_code) { |
| 2843 Label done, fail; | 2807 Label done, fail; |
| 2844 __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset)); | 2808 __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset)); |
| 2845 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 2809 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 2846 __ cmp(scratch, ip); | 2810 __ cmp(scratch, ip); |
| 2847 __ b(eq, &done); | 2811 __ b(eq, &done); |
| 2848 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); | 2812 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2863 __ bind(&fail); | 2827 __ bind(&fail); |
| 2864 __ Abort("Check for fast or external elements failed."); | 2828 __ Abort("Check for fast or external elements failed."); |
| 2865 __ bind(&done); | 2829 __ bind(&done); |
| 2866 } | 2830 } |
| 2867 } | 2831 } |
| 2868 | 2832 |
| 2869 | 2833 |
| 2870 void LCodeGen::DoLoadExternalArrayPointer( | 2834 void LCodeGen::DoLoadExternalArrayPointer( |
| 2871 LLoadExternalArrayPointer* instr) { | 2835 LLoadExternalArrayPointer* instr) { |
| 2872 Register to_reg = ToRegister(instr->result()); | 2836 Register to_reg = ToRegister(instr->result()); |
| 2873 Register from_reg = ToRegister(instr->object()); | 2837 Register from_reg = ToRegister(instr->InputAt(0)); |
| 2874 __ ldr(to_reg, FieldMemOperand(from_reg, | 2838 __ ldr(to_reg, FieldMemOperand(from_reg, |
| 2875 ExternalArray::kExternalPointerOffset)); | 2839 ExternalArray::kExternalPointerOffset)); |
| 2876 } | 2840 } |
| 2877 | 2841 |
| 2878 | 2842 |
| 2879 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2843 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 2880 Register arguments = ToRegister(instr->arguments()); | 2844 Register arguments = ToRegister(instr->arguments()); |
| 2881 Register length = ToRegister(instr->length()); | 2845 Register length = ToRegister(instr->length()); |
| 2882 Register index = ToRegister(instr->index()); | 2846 Register index = ToRegister(instr->index()); |
| 2883 Register result = ToRegister(instr->result()); | 2847 Register result = ToRegister(instr->result()); |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3120 | 3084 |
| 3121 // Result is the frame pointer for the frame if not adapted and for the real | 3085 // Result is the frame pointer for the frame if not adapted and for the real |
| 3122 // frame below the adaptor frame if adapted. | 3086 // frame below the adaptor frame if adapted. |
| 3123 __ mov(result, fp, LeaveCC, ne); | 3087 __ mov(result, fp, LeaveCC, ne); |
| 3124 __ mov(result, scratch, LeaveCC, eq); | 3088 __ mov(result, scratch, LeaveCC, eq); |
| 3125 } | 3089 } |
| 3126 } | 3090 } |
| 3127 | 3091 |
| 3128 | 3092 |
| 3129 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 3093 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
| 3130 Register elem = ToRegister(instr->elements()); | 3094 Register elem = ToRegister(instr->InputAt(0)); |
| 3131 Register result = ToRegister(instr->result()); | 3095 Register result = ToRegister(instr->result()); |
| 3132 | 3096 |
| 3133 Label done; | 3097 Label done; |
| 3134 | 3098 |
| 3135 // If no arguments adaptor frame the number of arguments is fixed. | 3099 // If no arguments adaptor frame the number of arguments is fixed. |
| 3136 __ cmp(fp, elem); | 3100 __ cmp(fp, elem); |
| 3137 __ mov(result, Operand(scope()->num_parameters())); | 3101 __ mov(result, Operand(scope()->num_parameters())); |
| 3138 __ b(eq, &done); | 3102 __ b(eq, &done); |
| 3139 | 3103 |
| 3140 // Arguments adaptor frame present. Get argument length from there. | 3104 // Arguments adaptor frame present. Get argument length from there. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3239 // The number of arguments is stored in receiver which is r0, as expected | 3203 // The number of arguments is stored in receiver which is r0, as expected |
| 3240 // by InvokeFunction. | 3204 // by InvokeFunction. |
| 3241 ParameterCount actual(receiver); | 3205 ParameterCount actual(receiver); |
| 3242 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3206 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 3243 safepoint_generator, CALL_AS_METHOD); | 3207 safepoint_generator, CALL_AS_METHOD); |
| 3244 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3208 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3245 } | 3209 } |
| 3246 | 3210 |
| 3247 | 3211 |
| 3248 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3212 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 3249 LOperand* argument = instr->value(); | 3213 LOperand* argument = instr->InputAt(0); |
| 3250 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3214 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
| 3251 Abort("DoPushArgument not implemented for double type."); | 3215 Abort("DoPushArgument not implemented for double type."); |
| 3252 } else { | 3216 } else { |
| 3253 Register argument_reg = EmitLoadRegister(argument, ip); | 3217 Register argument_reg = EmitLoadRegister(argument, ip); |
| 3254 __ push(argument_reg); | 3218 __ push(argument_reg); |
| 3255 } | 3219 } |
| 3256 } | 3220 } |
| 3257 | 3221 |
| 3258 | 3222 |
| 3259 void LCodeGen::DoDrop(LDrop* instr) { | 3223 void LCodeGen::DoDrop(LDrop* instr) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3291 } | 3255 } |
| 3292 | 3256 |
| 3293 | 3257 |
| 3294 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 3258 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
| 3295 Register result = ToRegister(instr->result()); | 3259 Register result = ToRegister(instr->result()); |
| 3296 __ ldr(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 3260 __ ldr(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); |
| 3297 } | 3261 } |
| 3298 | 3262 |
| 3299 | 3263 |
| 3300 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | 3264 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { |
| 3301 Register global = ToRegister(instr->global_object()); | 3265 Register global = ToRegister(instr->global()); |
| 3302 Register result = ToRegister(instr->result()); | 3266 Register result = ToRegister(instr->result()); |
| 3303 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); | 3267 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); |
| 3304 } | 3268 } |
| 3305 | 3269 |
| 3306 | 3270 |
| 3307 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3271 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 3308 int arity, | 3272 int arity, |
| 3309 LInstruction* instr, | 3273 LInstruction* instr, |
| 3310 CallKind call_kind, | 3274 CallKind call_kind, |
| 3311 R1State r1_state) { | 3275 R1State r1_state) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3351 ASSERT(ToRegister(instr->result()).is(r0)); | 3315 ASSERT(ToRegister(instr->result()).is(r0)); |
| 3352 CallKnownFunction(instr->function(), | 3316 CallKnownFunction(instr->function(), |
| 3353 instr->arity(), | 3317 instr->arity(), |
| 3354 instr, | 3318 instr, |
| 3355 CALL_AS_METHOD, | 3319 CALL_AS_METHOD, |
| 3356 R1_UNINITIALIZED); | 3320 R1_UNINITIALIZED); |
| 3357 } | 3321 } |
| 3358 | 3322 |
| 3359 | 3323 |
| 3360 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 3324 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 3361 Register input = ToRegister(instr->value()); | 3325 Register input = ToRegister(instr->InputAt(0)); |
| 3362 Register result = ToRegister(instr->result()); | 3326 Register result = ToRegister(instr->result()); |
| 3363 Register scratch = scratch0(); | 3327 Register scratch = scratch0(); |
| 3364 | 3328 |
| 3365 // Deoptimize if not a heap number. | 3329 // Deoptimize if not a heap number. |
| 3366 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3330 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 3367 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3331 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 3368 __ cmp(scratch, Operand(ip)); | 3332 __ cmp(scratch, Operand(ip)); |
| 3369 DeoptimizeIf(ne, instr->environment()); | 3333 DeoptimizeIf(ne, instr->environment()); |
| 3370 | 3334 |
| 3371 Label done; | 3335 Label done; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3417 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); | 3381 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
| 3418 | 3382 |
| 3419 __ StoreToSafepointRegisterSlot(tmp1, result); | 3383 __ StoreToSafepointRegisterSlot(tmp1, result); |
| 3420 } | 3384 } |
| 3421 | 3385 |
| 3422 __ bind(&done); | 3386 __ bind(&done); |
| 3423 } | 3387 } |
| 3424 | 3388 |
| 3425 | 3389 |
| 3426 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 3390 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
| 3427 Register input = ToRegister(instr->value()); | 3391 Register input = ToRegister(instr->InputAt(0)); |
| 3428 Register result = ToRegister(instr->result()); | 3392 Register result = ToRegister(instr->result()); |
| 3429 __ cmp(input, Operand(0)); | 3393 __ cmp(input, Operand(0)); |
| 3430 __ Move(result, input, pl); | 3394 __ Move(result, input, pl); |
| 3431 // We can make rsb conditional because the previous cmp instruction | 3395 // We can make rsb conditional because the previous cmp instruction |
| 3432 // will clear the V (overflow) flag and rsb won't set this flag | 3396 // will clear the V (overflow) flag and rsb won't set this flag |
| 3433 // if input is positive. | 3397 // if input is positive. |
| 3434 __ rsb(result, input, Operand(0), SetCC, mi); | 3398 __ rsb(result, input, Operand(0), SetCC, mi); |
| 3435 // Deoptimize on overflow. | 3399 // Deoptimize on overflow. |
| 3436 DeoptimizeIf(vs, instr->environment()); | 3400 DeoptimizeIf(vs, instr->environment()); |
| 3437 } | 3401 } |
| 3438 | 3402 |
| 3439 | 3403 |
| 3440 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 3404 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
| 3441 // Class for deferred case. | 3405 // Class for deferred case. |
| 3442 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3406 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
| 3443 public: | 3407 public: |
| 3444 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3408 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
| 3445 LUnaryMathOperation* instr) | 3409 LUnaryMathOperation* instr) |
| 3446 : LDeferredCode(codegen), instr_(instr) { } | 3410 : LDeferredCode(codegen), instr_(instr) { } |
| 3447 virtual void Generate() { | 3411 virtual void Generate() { |
| 3448 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3412 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 3449 } | 3413 } |
| 3450 virtual LInstruction* instr() { return instr_; } | 3414 virtual LInstruction* instr() { return instr_; } |
| 3451 private: | 3415 private: |
| 3452 LUnaryMathOperation* instr_; | 3416 LUnaryMathOperation* instr_; |
| 3453 }; | 3417 }; |
| 3454 | 3418 |
| 3455 Representation r = instr->hydrogen()->value()->representation(); | 3419 Representation r = instr->hydrogen()->value()->representation(); |
| 3456 if (r.IsDouble()) { | 3420 if (r.IsDouble()) { |
| 3457 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3421 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 3458 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3422 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 3459 __ vabs(result, input); | 3423 __ vabs(result, input); |
| 3460 } else if (r.IsInteger32()) { | 3424 } else if (r.IsInteger32()) { |
| 3461 EmitIntegerMathAbs(instr); | 3425 EmitIntegerMathAbs(instr); |
| 3462 } else { | 3426 } else { |
| 3463 // Representation is tagged. | 3427 // Representation is tagged. |
| 3464 DeferredMathAbsTaggedHeapNumber* deferred = | 3428 DeferredMathAbsTaggedHeapNumber* deferred = |
| 3465 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); | 3429 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
| 3466 Register input = ToRegister(instr->value()); | 3430 Register input = ToRegister(instr->InputAt(0)); |
| 3467 // Smi check. | 3431 // Smi check. |
| 3468 __ JumpIfNotSmi(input, deferred->entry()); | 3432 __ JumpIfNotSmi(input, deferred->entry()); |
| 3469 // If smi, handle it directly. | 3433 // If smi, handle it directly. |
| 3470 EmitIntegerMathAbs(instr); | 3434 EmitIntegerMathAbs(instr); |
| 3471 __ bind(deferred->exit()); | 3435 __ bind(deferred->exit()); |
| 3472 } | 3436 } |
| 3473 } | 3437 } |
| 3474 | 3438 |
| 3475 | 3439 |
| 3476 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 3440 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| 3477 DoubleRegister input = ToDoubleRegister(instr->value()); | 3441 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 3478 Register result = ToRegister(instr->result()); | 3442 Register result = ToRegister(instr->result()); |
| 3479 SwVfpRegister single_scratch = double_scratch0().low(); | 3443 SwVfpRegister single_scratch = double_scratch0().low(); |
| 3480 Register scratch1 = scratch0(); | 3444 Register scratch1 = scratch0(); |
| 3481 Register scratch2 = ToRegister(instr->temp()); | 3445 Register scratch2 = ToRegister(instr->TempAt(0)); |
| 3482 | 3446 |
| 3483 __ EmitVFPTruncate(kRoundToMinusInf, | 3447 __ EmitVFPTruncate(kRoundToMinusInf, |
| 3484 single_scratch, | 3448 single_scratch, |
| 3485 input, | 3449 input, |
| 3486 scratch1, | 3450 scratch1, |
| 3487 scratch2); | 3451 scratch2); |
| 3488 DeoptimizeIf(ne, instr->environment()); | 3452 DeoptimizeIf(ne, instr->environment()); |
| 3489 | 3453 |
| 3490 // Move the result back to general purpose register r0. | 3454 // Move the result back to general purpose register r0. |
| 3491 __ vmov(result, single_scratch); | 3455 __ vmov(result, single_scratch); |
| 3492 | 3456 |
| 3493 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3457 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3494 // Test for -0. | 3458 // Test for -0. |
| 3495 Label done; | 3459 Label done; |
| 3496 __ cmp(result, Operand(0)); | 3460 __ cmp(result, Operand(0)); |
| 3497 __ b(ne, &done); | 3461 __ b(ne, &done); |
| 3498 __ vmov(scratch1, input.high()); | 3462 __ vmov(scratch1, input.high()); |
| 3499 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 3463 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
| 3500 DeoptimizeIf(ne, instr->environment()); | 3464 DeoptimizeIf(ne, instr->environment()); |
| 3501 __ bind(&done); | 3465 __ bind(&done); |
| 3502 } | 3466 } |
| 3503 } | 3467 } |
| 3504 | 3468 |
| 3505 | 3469 |
| 3506 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 3470 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| 3507 DoubleRegister input = ToDoubleRegister(instr->value()); | 3471 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 3508 Register result = ToRegister(instr->result()); | 3472 Register result = ToRegister(instr->result()); |
| 3509 Register scratch = scratch0(); | 3473 Register scratch = scratch0(); |
| 3510 Label done, check_sign_on_zero; | 3474 Label done, check_sign_on_zero; |
| 3511 | 3475 |
| 3512 // Extract exponent bits. | 3476 // Extract exponent bits. |
| 3513 __ vmov(result, input.high()); | 3477 __ vmov(result, input.high()); |
| 3514 __ ubfx(scratch, | 3478 __ ubfx(scratch, |
| 3515 result, | 3479 result, |
| 3516 HeapNumber::kExponentShift, | 3480 HeapNumber::kExponentShift, |
| 3517 HeapNumber::kExponentBits); | 3481 HeapNumber::kExponentBits); |
| 3518 | 3482 |
| 3519 // If the number is in ]-0.5, +0.5[, the result is +/- 0. | 3483 // If the number is in ]-0.5, +0.5[, the result is +/- 0. |
| 3520 __ cmp(scratch, Operand(HeapNumber::kExponentBias - 2)); | 3484 __ cmp(scratch, Operand(HeapNumber::kExponentBias - 2)); |
| 3521 __ mov(result, Operand(0), LeaveCC, le); | 3485 __ mov(result, Operand(0), LeaveCC, le); |
| 3522 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3486 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3523 __ b(le, &check_sign_on_zero); | 3487 __ b(le, &check_sign_on_zero); |
| 3524 } else { | 3488 } else { |
| 3525 __ b(le, &done); | 3489 __ b(le, &done); |
| 3526 } | 3490 } |
| 3527 | 3491 |
| 3528 // The following conversion will not work with numbers | 3492 // The following conversion will not work with numbers |
| 3529 // outside of ]-2^32, 2^32[. | 3493 // outside of ]-2^32, 2^32[. |
| 3530 __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32)); | 3494 __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32)); |
| 3531 DeoptimizeIf(ge, instr->environment()); | 3495 DeoptimizeIf(ge, instr->environment()); |
| 3532 | 3496 |
| 3533 __ Vmov(double_scratch0(), 0.5, scratch); | |
| 3534 __ vadd(double_scratch0(), input, double_scratch0()); | |
| 3535 | |
| 3536 // Save the original sign for later comparison. | 3497 // Save the original sign for later comparison. |
| 3537 __ and_(scratch, result, Operand(HeapNumber::kSignMask)); | 3498 __ and_(scratch, result, Operand(HeapNumber::kSignMask)); |
| 3538 | 3499 |
| 3500 __ Vmov(double_scratch0(), 0.5); |
| 3501 __ vadd(double_scratch0(), input, double_scratch0()); |
| 3502 |
| 3539 // Check sign of the result: if the sign changed, the input | 3503 // Check sign of the result: if the sign changed, the input |
| 3540 // value was in ]0.5, 0[ and the result should be -0. | 3504 // value was in ]0.5, 0[ and the result should be -0. |
| 3541 __ vmov(result, double_scratch0().high()); | 3505 __ vmov(result, double_scratch0().high()); |
| 3542 __ eor(result, result, Operand(scratch), SetCC); | 3506 __ eor(result, result, Operand(scratch), SetCC); |
| 3543 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3507 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3544 DeoptimizeIf(mi, instr->environment()); | 3508 DeoptimizeIf(mi, instr->environment()); |
| 3545 } else { | 3509 } else { |
| 3546 __ mov(result, Operand(0), LeaveCC, mi); | 3510 __ mov(result, Operand(0), LeaveCC, mi); |
| 3547 __ b(mi, &done); | 3511 __ b(mi, &done); |
| 3548 } | 3512 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3562 __ bind(&check_sign_on_zero); | 3526 __ bind(&check_sign_on_zero); |
| 3563 __ vmov(scratch, input.high()); | 3527 __ vmov(scratch, input.high()); |
| 3564 __ tst(scratch, Operand(HeapNumber::kSignMask)); | 3528 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
| 3565 DeoptimizeIf(ne, instr->environment()); | 3529 DeoptimizeIf(ne, instr->environment()); |
| 3566 } | 3530 } |
| 3567 __ bind(&done); | 3531 __ bind(&done); |
| 3568 } | 3532 } |
| 3569 | 3533 |
| 3570 | 3534 |
| 3571 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3535 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| 3572 DoubleRegister input = ToDoubleRegister(instr->value()); | 3536 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 3573 DoubleRegister result = ToDoubleRegister(instr->result()); | 3537 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3574 __ vsqrt(result, input); | 3538 __ vsqrt(result, input); |
| 3575 } | 3539 } |
| 3576 | 3540 |
| 3577 | 3541 |
| 3578 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3542 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
| 3579 DoubleRegister input = ToDoubleRegister(instr->value()); | 3543 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 3580 DoubleRegister result = ToDoubleRegister(instr->result()); | 3544 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3581 DoubleRegister temp = ToDoubleRegister(instr->temp()); | 3545 DoubleRegister temp = ToDoubleRegister(instr->TempAt(0)); |
| 3582 | 3546 |
| 3583 // Note that according to ECMA-262 15.8.2.13: | 3547 // Note that according to ECMA-262 15.8.2.13: |
| 3584 // Math.pow(-Infinity, 0.5) == Infinity | 3548 // Math.pow(-Infinity, 0.5) == Infinity |
| 3585 // Math.sqrt(-Infinity) == NaN | 3549 // Math.sqrt(-Infinity) == NaN |
| 3586 Label done; | 3550 Label done; |
| 3587 __ vmov(temp, -V8_INFINITY, scratch0()); | 3551 __ vmov(temp, -V8_INFINITY); |
| 3588 __ VFPCompareAndSetFlags(input, temp); | 3552 __ VFPCompareAndSetFlags(input, temp); |
| 3589 __ vneg(result, temp, eq); | 3553 __ vneg(result, temp, eq); |
| 3590 __ b(&done, eq); | 3554 __ b(&done, eq); |
| 3591 | 3555 |
| 3592 // Add +0 to convert -0 to +0. | 3556 // Add +0 to convert -0 to +0. |
| 3593 __ vadd(result, input, kDoubleRegZero); | 3557 __ vadd(result, input, kDoubleRegZero); |
| 3594 __ vsqrt(result, result); | 3558 __ vsqrt(result, result); |
| 3595 __ bind(&done); | 3559 __ bind(&done); |
| 3596 } | 3560 } |
| 3597 | 3561 |
| 3598 | 3562 |
| 3599 void LCodeGen::DoPower(LPower* instr) { | 3563 void LCodeGen::DoPower(LPower* instr) { |
| 3600 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3564 Representation exponent_type = instr->hydrogen()->right()->representation(); |
| 3601 // Having marked this as a call, we can use any registers. | 3565 // Having marked this as a call, we can use any registers. |
| 3602 // Just make sure that the input/output registers are the expected ones. | 3566 // Just make sure that the input/output registers are the expected ones. |
| 3603 ASSERT(!instr->right()->IsDoubleRegister() || | 3567 ASSERT(!instr->InputAt(1)->IsDoubleRegister() || |
| 3604 ToDoubleRegister(instr->right()).is(d2)); | 3568 ToDoubleRegister(instr->InputAt(1)).is(d2)); |
| 3605 ASSERT(!instr->right()->IsRegister() || | 3569 ASSERT(!instr->InputAt(1)->IsRegister() || |
| 3606 ToRegister(instr->right()).is(r2)); | 3570 ToRegister(instr->InputAt(1)).is(r2)); |
| 3607 ASSERT(ToDoubleRegister(instr->left()).is(d1)); | 3571 ASSERT(ToDoubleRegister(instr->InputAt(0)).is(d1)); |
| 3608 ASSERT(ToDoubleRegister(instr->result()).is(d3)); | 3572 ASSERT(ToDoubleRegister(instr->result()).is(d3)); |
| 3609 | 3573 |
| 3610 if (exponent_type.IsTagged()) { | 3574 if (exponent_type.IsTagged()) { |
| 3611 Label no_deopt; | 3575 Label no_deopt; |
| 3612 __ JumpIfSmi(r2, &no_deopt); | 3576 __ JumpIfSmi(r2, &no_deopt); |
| 3613 __ ldr(r7, FieldMemOperand(r2, HeapObject::kMapOffset)); | 3577 __ ldr(r7, FieldMemOperand(r2, HeapObject::kMapOffset)); |
| 3614 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3578 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 3615 __ cmp(r7, Operand(ip)); | 3579 __ cmp(r7, Operand(ip)); |
| 3616 DeoptimizeIf(ne, instr->environment()); | 3580 DeoptimizeIf(ne, instr->environment()); |
| 3617 __ bind(&no_deopt); | 3581 __ bind(&no_deopt); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3637 virtual LInstruction* instr() { return instr_; } | 3601 virtual LInstruction* instr() { return instr_; } |
| 3638 private: | 3602 private: |
| 3639 LRandom* instr_; | 3603 LRandom* instr_; |
| 3640 }; | 3604 }; |
| 3641 | 3605 |
| 3642 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); | 3606 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); |
| 3643 | 3607 |
| 3644 // Having marked this instruction as a call we can use any | 3608 // Having marked this instruction as a call we can use any |
| 3645 // registers. | 3609 // registers. |
| 3646 ASSERT(ToDoubleRegister(instr->result()).is(d7)); | 3610 ASSERT(ToDoubleRegister(instr->result()).is(d7)); |
| 3647 ASSERT(ToRegister(instr->global_object()).is(r0)); | 3611 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); |
| 3648 | 3612 |
| 3649 static const int kSeedSize = sizeof(uint32_t); | 3613 static const int kSeedSize = sizeof(uint32_t); |
| 3650 STATIC_ASSERT(kPointerSize == kSeedSize); | 3614 STATIC_ASSERT(kPointerSize == kSeedSize); |
| 3651 | 3615 |
| 3652 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset)); | 3616 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset)); |
| 3653 static const int kRandomSeedOffset = | 3617 static const int kRandomSeedOffset = |
| 3654 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; | 3618 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; |
| 3655 __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset)); | 3619 __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset)); |
| 3656 // r2: FixedArray of the native context's random seeds | 3620 // r2: FixedArray of the native context's random seeds |
| 3657 | 3621 |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3848 ASSERT(ToRegister(instr->result()).is(r0)); | 3812 ASSERT(ToRegister(instr->result()).is(r0)); |
| 3849 CallKnownFunction(instr->target(), | 3813 CallKnownFunction(instr->target(), |
| 3850 instr->arity(), | 3814 instr->arity(), |
| 3851 instr, | 3815 instr, |
| 3852 CALL_AS_FUNCTION, | 3816 CALL_AS_FUNCTION, |
| 3853 R1_UNINITIALIZED); | 3817 R1_UNINITIALIZED); |
| 3854 } | 3818 } |
| 3855 | 3819 |
| 3856 | 3820 |
| 3857 void LCodeGen::DoCallNew(LCallNew* instr) { | 3821 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 3858 ASSERT(ToRegister(instr->constructor()).is(r1)); | 3822 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); |
| 3859 ASSERT(ToRegister(instr->result()).is(r0)); | 3823 ASSERT(ToRegister(instr->result()).is(r0)); |
| 3860 | 3824 |
| 3861 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3825 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| 3862 __ mov(r0, Operand(instr->arity())); | 3826 __ mov(r0, Operand(instr->arity())); |
| 3863 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 3827 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
| 3864 } | 3828 } |
| 3865 | 3829 |
| 3866 | 3830 |
| 3867 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3831 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 3868 CallRuntime(instr->function(), instr->arity(), instr); | 3832 CallRuntime(instr->function(), instr->arity(), instr); |
| 3869 } | 3833 } |
| 3870 | 3834 |
| 3871 | 3835 |
| 3872 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3836 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
| 3873 Register object = ToRegister(instr->object()); | 3837 Register object = ToRegister(instr->object()); |
| 3874 Register value = ToRegister(instr->value()); | 3838 Register value = ToRegister(instr->value()); |
| 3875 Register scratch = scratch0(); | 3839 Register scratch = scratch0(); |
| 3876 int offset = instr->offset(); | 3840 int offset = instr->offset(); |
| 3877 | 3841 |
| 3878 ASSERT(!object.is(value)); | 3842 ASSERT(!object.is(value)); |
| 3879 | 3843 |
| 3880 if (!instr->transition().is_null()) { | 3844 if (!instr->transition().is_null()) { |
| 3881 __ mov(scratch, Operand(instr->transition())); | 3845 __ mov(scratch, Operand(instr->transition())); |
| 3882 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 3846 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 3883 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { | 3847 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { |
| 3884 Register temp = ToRegister(instr->temp()); | 3848 Register temp = ToRegister(instr->TempAt(0)); |
| 3885 // Update the write barrier for the map field. | 3849 // Update the write barrier for the map field. |
| 3886 __ RecordWriteField(object, | 3850 __ RecordWriteField(object, |
| 3887 HeapObject::kMapOffset, | 3851 HeapObject::kMapOffset, |
| 3888 scratch, | 3852 scratch, |
| 3889 temp, | 3853 temp, |
| 3890 kLRHasBeenSaved, | 3854 kLRHasBeenSaved, |
| 3891 kSaveFPRegs, | 3855 kSaveFPRegs, |
| 3892 OMIT_REMEMBERED_SET, | 3856 OMIT_REMEMBERED_SET, |
| 3893 OMIT_SMI_CHECK); | 3857 OMIT_SMI_CHECK); |
| 3894 } | 3858 } |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4059 __ add(scratch, scratch, | 4023 __ add(scratch, scratch, |
| 4060 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); | 4024 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 4061 } | 4025 } |
| 4062 | 4026 |
| 4063 if (instr->NeedsCanonicalization()) { | 4027 if (instr->NeedsCanonicalization()) { |
| 4064 // Check for NaN. All NaNs must be canonicalized. | 4028 // Check for NaN. All NaNs must be canonicalized. |
| 4065 __ VFPCompareAndSetFlags(value, value); | 4029 __ VFPCompareAndSetFlags(value, value); |
| 4066 // Only load canonical NaN if the comparison above set the overflow. | 4030 // Only load canonical NaN if the comparison above set the overflow. |
| 4067 __ Vmov(value, | 4031 __ Vmov(value, |
| 4068 FixedDoubleArray::canonical_not_the_hole_nan_as_double(), | 4032 FixedDoubleArray::canonical_not_the_hole_nan_as_double(), |
| 4069 no_reg, vs); | 4033 vs); |
| 4070 } | 4034 } |
| 4071 | 4035 |
| 4072 __ vstr(value, scratch, instr->additional_index() << element_size_shift); | 4036 __ vstr(value, scratch, instr->additional_index() << element_size_shift); |
| 4073 } | 4037 } |
| 4074 | 4038 |
| 4075 | 4039 |
| 4076 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | 4040 void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
| 4077 LStoreKeyedSpecializedArrayElement* instr) { | 4041 LStoreKeyedSpecializedArrayElement* instr) { |
| 4078 | 4042 |
| 4079 Register external_pointer = ToRegister(instr->external_pointer()); | 4043 Register external_pointer = ToRegister(instr->external_pointer()); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4152 | 4116 |
| 4153 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4117 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 4154 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4118 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 4155 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4119 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 4156 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4120 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4157 } | 4121 } |
| 4158 | 4122 |
| 4159 | 4123 |
| 4160 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 4124 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
| 4161 Register object_reg = ToRegister(instr->object()); | 4125 Register object_reg = ToRegister(instr->object()); |
| 4162 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4126 Register new_map_reg = ToRegister(instr->new_map_reg()); |
| 4163 Register scratch = scratch0(); | 4127 Register scratch = scratch0(); |
| 4164 | 4128 |
| 4165 Handle<Map> from_map = instr->original_map(); | 4129 Handle<Map> from_map = instr->original_map(); |
| 4166 Handle<Map> to_map = instr->transitioned_map(); | 4130 Handle<Map> to_map = instr->transitioned_map(); |
| 4167 ElementsKind from_kind = from_map->elements_kind(); | 4131 ElementsKind from_kind = from_map->elements_kind(); |
| 4168 ElementsKind to_kind = to_map->elements_kind(); | 4132 ElementsKind to_kind = to_map->elements_kind(); |
| 4169 | 4133 |
| 4170 Label not_applicable; | 4134 Label not_applicable; |
| 4171 __ ldr(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4135 __ ldr(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 4172 __ cmp(scratch, Operand(from_map)); | 4136 __ cmp(scratch, Operand(from_map)); |
| 4173 __ b(ne, ¬_applicable); | 4137 __ b(ne, ¬_applicable); |
| 4174 __ mov(new_map_reg, Operand(to_map)); | 4138 __ mov(new_map_reg, Operand(to_map)); |
| 4175 | 4139 |
| 4176 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 4140 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 4177 __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4141 __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 4178 // Write barrier. | 4142 // Write barrier. |
| 4179 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 4143 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
| 4180 scratch, kLRHasBeenSaved, kDontSaveFPRegs); | 4144 scratch, kLRHasBeenSaved, kDontSaveFPRegs); |
| 4181 } else if (IsFastSmiElementsKind(from_kind) && | 4145 } else if (IsFastSmiElementsKind(from_kind) && |
| 4182 IsFastDoubleElementsKind(to_kind)) { | 4146 IsFastDoubleElementsKind(to_kind)) { |
| 4183 Register fixed_object_reg = ToRegister(instr->temp()); | 4147 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
| 4184 ASSERT(fixed_object_reg.is(r2)); | 4148 ASSERT(fixed_object_reg.is(r2)); |
| 4185 ASSERT(new_map_reg.is(r3)); | 4149 ASSERT(new_map_reg.is(r3)); |
| 4186 __ mov(fixed_object_reg, object_reg); | 4150 __ mov(fixed_object_reg, object_reg); |
| 4187 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 4151 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
| 4188 RelocInfo::CODE_TARGET, instr); | 4152 RelocInfo::CODE_TARGET, instr); |
| 4189 } else if (IsFastDoubleElementsKind(from_kind) && | 4153 } else if (IsFastDoubleElementsKind(from_kind) && |
| 4190 IsFastObjectElementsKind(to_kind)) { | 4154 IsFastObjectElementsKind(to_kind)) { |
| 4191 Register fixed_object_reg = ToRegister(instr->temp()); | 4155 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
| 4192 ASSERT(fixed_object_reg.is(r2)); | 4156 ASSERT(fixed_object_reg.is(r2)); |
| 4193 ASSERT(new_map_reg.is(r3)); | 4157 ASSERT(new_map_reg.is(r3)); |
| 4194 __ mov(fixed_object_reg, object_reg); | 4158 __ mov(fixed_object_reg, object_reg); |
| 4195 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 4159 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
| 4196 RelocInfo::CODE_TARGET, instr); | 4160 RelocInfo::CODE_TARGET, instr); |
| 4197 } else { | 4161 } else { |
| 4198 UNREACHABLE(); | 4162 UNREACHABLE(); |
| 4199 } | 4163 } |
| 4200 __ bind(¬_applicable); | 4164 __ bind(¬_applicable); |
| 4201 } | 4165 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4306 | 4270 |
| 4307 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4271 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 4308 __ SmiTag(char_code); | 4272 __ SmiTag(char_code); |
| 4309 __ push(char_code); | 4273 __ push(char_code); |
| 4310 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 4274 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); |
| 4311 __ StoreToSafepointRegisterSlot(r0, result); | 4275 __ StoreToSafepointRegisterSlot(r0, result); |
| 4312 } | 4276 } |
| 4313 | 4277 |
| 4314 | 4278 |
| 4315 void LCodeGen::DoStringLength(LStringLength* instr) { | 4279 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 4316 Register string = ToRegister(instr->string()); | 4280 Register string = ToRegister(instr->InputAt(0)); |
| 4317 Register result = ToRegister(instr->result()); | 4281 Register result = ToRegister(instr->result()); |
| 4318 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); | 4282 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); |
| 4319 } | 4283 } |
| 4320 | 4284 |
| 4321 | 4285 |
| 4322 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4286 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 4323 LOperand* input = instr->value(); | 4287 LOperand* input = instr->InputAt(0); |
| 4324 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4288 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 4325 LOperand* output = instr->result(); | 4289 LOperand* output = instr->result(); |
| 4326 ASSERT(output->IsDoubleRegister()); | 4290 ASSERT(output->IsDoubleRegister()); |
| 4327 SwVfpRegister single_scratch = double_scratch0().low(); | 4291 SwVfpRegister single_scratch = double_scratch0().low(); |
| 4328 if (input->IsStackSlot()) { | 4292 if (input->IsStackSlot()) { |
| 4329 Register scratch = scratch0(); | 4293 Register scratch = scratch0(); |
| 4330 __ ldr(scratch, ToMemOperand(input)); | 4294 __ ldr(scratch, ToMemOperand(input)); |
| 4331 __ vmov(single_scratch, scratch); | 4295 __ vmov(single_scratch, scratch); |
| 4332 } else { | 4296 } else { |
| 4333 __ vmov(single_scratch, ToRegister(input)); | 4297 __ vmov(single_scratch, ToRegister(input)); |
| 4334 } | 4298 } |
| 4335 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); | 4299 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); |
| 4336 } | 4300 } |
| 4337 | 4301 |
| 4338 | 4302 |
| 4339 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4303 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
| 4340 LOperand* input = instr->value(); | 4304 LOperand* input = instr->InputAt(0); |
| 4341 LOperand* output = instr->result(); | 4305 LOperand* output = instr->result(); |
| 4342 | 4306 |
| 4343 SwVfpRegister flt_scratch = double_scratch0().low(); | 4307 SwVfpRegister flt_scratch = double_scratch0().low(); |
| 4344 __ vmov(flt_scratch, ToRegister(input)); | 4308 __ vmov(flt_scratch, ToRegister(input)); |
| 4345 __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); | 4309 __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); |
| 4346 } | 4310 } |
| 4347 | 4311 |
| 4348 | 4312 |
| 4349 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4313 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 4350 class DeferredNumberTagI: public LDeferredCode { | 4314 class DeferredNumberTagI: public LDeferredCode { |
| 4351 public: | 4315 public: |
| 4352 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 4316 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
| 4353 : LDeferredCode(codegen), instr_(instr) { } | 4317 : LDeferredCode(codegen), instr_(instr) { } |
| 4354 virtual void Generate() { | 4318 virtual void Generate() { |
| 4355 codegen()->DoDeferredNumberTagI(instr_, | 4319 codegen()->DoDeferredNumberTagI(instr_, |
| 4356 instr_->value(), | 4320 instr_->InputAt(0), |
| 4357 SIGNED_INT32); | 4321 SIGNED_INT32); |
| 4358 } | 4322 } |
| 4359 virtual LInstruction* instr() { return instr_; } | 4323 virtual LInstruction* instr() { return instr_; } |
| 4360 private: | 4324 private: |
| 4361 LNumberTagI* instr_; | 4325 LNumberTagI* instr_; |
| 4362 }; | 4326 }; |
| 4363 | 4327 |
| 4364 Register src = ToRegister(instr->value()); | 4328 Register src = ToRegister(instr->InputAt(0)); |
| 4365 Register dst = ToRegister(instr->result()); | 4329 Register dst = ToRegister(instr->result()); |
| 4366 | 4330 |
| 4367 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); | 4331 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
| 4368 __ SmiTag(dst, src, SetCC); | 4332 __ SmiTag(dst, src, SetCC); |
| 4369 __ b(vs, deferred->entry()); | 4333 __ b(vs, deferred->entry()); |
| 4370 __ bind(deferred->exit()); | 4334 __ bind(deferred->exit()); |
| 4371 } | 4335 } |
| 4372 | 4336 |
| 4373 | 4337 |
| 4374 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4338 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
| 4375 class DeferredNumberTagU: public LDeferredCode { | 4339 class DeferredNumberTagU: public LDeferredCode { |
| 4376 public: | 4340 public: |
| 4377 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4341 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
| 4378 : LDeferredCode(codegen), instr_(instr) { } | 4342 : LDeferredCode(codegen), instr_(instr) { } |
| 4379 virtual void Generate() { | 4343 virtual void Generate() { |
| 4380 codegen()->DoDeferredNumberTagI(instr_, | 4344 codegen()->DoDeferredNumberTagI(instr_, |
| 4381 instr_->value(), | 4345 instr_->InputAt(0), |
| 4382 UNSIGNED_INT32); | 4346 UNSIGNED_INT32); |
| 4383 } | 4347 } |
| 4384 virtual LInstruction* instr() { return instr_; } | 4348 virtual LInstruction* instr() { return instr_; } |
| 4385 private: | 4349 private: |
| 4386 LNumberTagU* instr_; | 4350 LNumberTagU* instr_; |
| 4387 }; | 4351 }; |
| 4388 | 4352 |
| 4389 LOperand* input = instr->value(); | 4353 LOperand* input = instr->InputAt(0); |
| 4390 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4354 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4391 Register reg = ToRegister(input); | 4355 Register reg = ToRegister(input); |
| 4392 | 4356 |
| 4393 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4357 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
| 4394 __ cmp(reg, Operand(Smi::kMaxValue)); | 4358 __ cmp(reg, Operand(Smi::kMaxValue)); |
| 4395 __ b(hi, deferred->entry()); | 4359 __ b(hi, deferred->entry()); |
| 4396 __ SmiTag(reg, reg); | 4360 __ SmiTag(reg, reg); |
| 4397 __ bind(deferred->exit()); | 4361 __ bind(deferred->exit()); |
| 4398 } | 4362 } |
| 4399 | 4363 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4457 class DeferredNumberTagD: public LDeferredCode { | 4421 class DeferredNumberTagD: public LDeferredCode { |
| 4458 public: | 4422 public: |
| 4459 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4423 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 4460 : LDeferredCode(codegen), instr_(instr) { } | 4424 : LDeferredCode(codegen), instr_(instr) { } |
| 4461 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4425 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
| 4462 virtual LInstruction* instr() { return instr_; } | 4426 virtual LInstruction* instr() { return instr_; } |
| 4463 private: | 4427 private: |
| 4464 LNumberTagD* instr_; | 4428 LNumberTagD* instr_; |
| 4465 }; | 4429 }; |
| 4466 | 4430 |
| 4467 DoubleRegister input_reg = ToDoubleRegister(instr->value()); | 4431 DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 4468 Register scratch = scratch0(); | 4432 Register scratch = scratch0(); |
| 4469 Register reg = ToRegister(instr->result()); | 4433 Register reg = ToRegister(instr->result()); |
| 4470 Register temp1 = ToRegister(instr->temp()); | 4434 Register temp1 = ToRegister(instr->TempAt(0)); |
| 4471 Register temp2 = ToRegister(instr->temp2()); | 4435 Register temp2 = ToRegister(instr->TempAt(1)); |
| 4472 | 4436 |
| 4473 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4437 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
| 4474 if (FLAG_inline_new) { | 4438 if (FLAG_inline_new) { |
| 4475 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4439 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 4476 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); | 4440 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); |
| 4477 } else { | 4441 } else { |
| 4478 __ jmp(deferred->entry()); | 4442 __ jmp(deferred->entry()); |
| 4479 } | 4443 } |
| 4480 __ bind(deferred->exit()); | 4444 __ bind(deferred->exit()); |
| 4481 __ sub(ip, reg, Operand(kHeapObjectTag)); | 4445 __ sub(ip, reg, Operand(kHeapObjectTag)); |
| 4482 __ vstr(input_reg, ip, HeapNumber::kValueOffset); | 4446 __ vstr(input_reg, ip, HeapNumber::kValueOffset); |
| 4483 } | 4447 } |
| 4484 | 4448 |
| 4485 | 4449 |
| 4486 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4450 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4487 // TODO(3095996): Get rid of this. For now, we need to make the | 4451 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4488 // result register contain a valid pointer because it is already | 4452 // result register contain a valid pointer because it is already |
| 4489 // contained in the register pointer map. | 4453 // contained in the register pointer map. |
| 4490 Register reg = ToRegister(instr->result()); | 4454 Register reg = ToRegister(instr->result()); |
| 4491 __ mov(reg, Operand(0)); | 4455 __ mov(reg, Operand(0)); |
| 4492 | 4456 |
| 4493 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4457 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 4494 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4458 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
| 4495 __ StoreToSafepointRegisterSlot(r0, reg); | 4459 __ StoreToSafepointRegisterSlot(r0, reg); |
| 4496 } | 4460 } |
| 4497 | 4461 |
| 4498 | 4462 |
| 4499 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4463 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 4500 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 4464 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| 4501 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->value())); | 4465 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->InputAt(0))); |
| 4502 } | 4466 } |
| 4503 | 4467 |
| 4504 | 4468 |
| 4505 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4469 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 4506 Register input = ToRegister(instr->value()); | 4470 Register input = ToRegister(instr->InputAt(0)); |
| 4507 Register result = ToRegister(instr->result()); | 4471 Register result = ToRegister(instr->result()); |
| 4508 if (instr->needs_check()) { | 4472 if (instr->needs_check()) { |
| 4509 STATIC_ASSERT(kHeapObjectTag == 1); | 4473 STATIC_ASSERT(kHeapObjectTag == 1); |
| 4510 // If the input is a HeapObject, SmiUntag will set the carry flag. | 4474 // If the input is a HeapObject, SmiUntag will set the carry flag. |
| 4511 __ SmiUntag(result, input, SetCC); | 4475 __ SmiUntag(result, input, SetCC); |
| 4512 DeoptimizeIf(cs, instr->environment()); | 4476 DeoptimizeIf(cs, instr->environment()); |
| 4513 } else { | 4477 } else { |
| 4514 __ SmiUntag(result, input); | 4478 __ SmiUntag(result, input); |
| 4515 } | 4479 } |
| 4516 } | 4480 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4568 // Smi to double register conversion | 4532 // Smi to double register conversion |
| 4569 __ bind(&load_smi); | 4533 __ bind(&load_smi); |
| 4570 // scratch: untagged value of input_reg | 4534 // scratch: untagged value of input_reg |
| 4571 __ vmov(flt_scratch, scratch); | 4535 __ vmov(flt_scratch, scratch); |
| 4572 __ vcvt_f64_s32(result_reg, flt_scratch); | 4536 __ vcvt_f64_s32(result_reg, flt_scratch); |
| 4573 __ bind(&done); | 4537 __ bind(&done); |
| 4574 } | 4538 } |
| 4575 | 4539 |
| 4576 | 4540 |
| 4577 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 4541 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 4578 Register input_reg = ToRegister(instr->value()); | 4542 Register input_reg = ToRegister(instr->InputAt(0)); |
| 4579 Register scratch1 = scratch0(); | 4543 Register scratch1 = scratch0(); |
| 4580 Register scratch2 = ToRegister(instr->temp()); | 4544 Register scratch2 = ToRegister(instr->TempAt(0)); |
| 4581 DwVfpRegister double_scratch = double_scratch0(); | 4545 DwVfpRegister double_scratch = double_scratch0(); |
| 4582 SwVfpRegister single_scratch = double_scratch.low(); | 4546 SwVfpRegister single_scratch = double_scratch.low(); |
| 4583 | 4547 |
| 4584 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); | 4548 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); |
| 4585 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); | 4549 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); |
| 4586 | 4550 |
| 4587 Label done; | 4551 Label done; |
| 4588 | 4552 |
| 4589 // The input was optimistically untagged; revert it. | 4553 // The input was optimistically untagged; revert it. |
| 4590 // The carry flag is set when we reach this deferred code as we just executed | 4554 // The carry flag is set when we reach this deferred code as we just executed |
| 4591 // SmiUntag(heap_object, SetCC) | 4555 // SmiUntag(heap_object, SetCC) |
| 4592 STATIC_ASSERT(kHeapObjectTag == 1); | 4556 STATIC_ASSERT(kHeapObjectTag == 1); |
| 4593 __ adc(input_reg, input_reg, Operand(input_reg)); | 4557 __ adc(input_reg, input_reg, Operand(input_reg)); |
| 4594 | 4558 |
| 4595 // Heap number map check. | 4559 // Heap number map check. |
| 4596 __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4560 __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4597 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4561 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 4598 __ cmp(scratch1, Operand(ip)); | 4562 __ cmp(scratch1, Operand(ip)); |
| 4599 | 4563 |
| 4600 if (instr->truncating()) { | 4564 if (instr->truncating()) { |
| 4601 Register scratch3 = ToRegister(instr->temp2()); | 4565 Register scratch3 = ToRegister(instr->TempAt(1)); |
| 4602 DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3()); | 4566 DwVfpRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2)); |
| 4603 ASSERT(!scratch3.is(input_reg) && | 4567 ASSERT(!scratch3.is(input_reg) && |
| 4604 !scratch3.is(scratch1) && | 4568 !scratch3.is(scratch1) && |
| 4605 !scratch3.is(scratch2)); | 4569 !scratch3.is(scratch2)); |
| 4606 // Performs a truncating conversion of a floating point number as used by | 4570 // Performs a truncating conversion of a floating point number as used by |
| 4607 // the JS bitwise operations. | 4571 // the JS bitwise operations. |
| 4608 Label heap_number; | 4572 Label heap_number; |
| 4609 __ b(eq, &heap_number); | 4573 __ b(eq, &heap_number); |
| 4610 // Check for undefined. Undefined is converted to zero for truncating | 4574 // Check for undefined. Undefined is converted to zero for truncating |
| 4611 // conversions. | 4575 // conversions. |
| 4612 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4576 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4659 class DeferredTaggedToI: public LDeferredCode { | 4623 class DeferredTaggedToI: public LDeferredCode { |
| 4660 public: | 4624 public: |
| 4661 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4625 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 4662 : LDeferredCode(codegen), instr_(instr) { } | 4626 : LDeferredCode(codegen), instr_(instr) { } |
| 4663 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 4627 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
| 4664 virtual LInstruction* instr() { return instr_; } | 4628 virtual LInstruction* instr() { return instr_; } |
| 4665 private: | 4629 private: |
| 4666 LTaggedToI* instr_; | 4630 LTaggedToI* instr_; |
| 4667 }; | 4631 }; |
| 4668 | 4632 |
| 4669 LOperand* input = instr->value(); | 4633 LOperand* input = instr->InputAt(0); |
| 4670 ASSERT(input->IsRegister()); | 4634 ASSERT(input->IsRegister()); |
| 4671 ASSERT(input->Equals(instr->result())); | 4635 ASSERT(input->Equals(instr->result())); |
| 4672 | 4636 |
| 4673 Register input_reg = ToRegister(input); | 4637 Register input_reg = ToRegister(input); |
| 4674 | 4638 |
| 4675 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | 4639 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
| 4676 | 4640 |
| 4677 // Optimistically untag the input. | 4641 // Optimistically untag the input. |
| 4678 // If the input is a HeapObject, SmiUntag will set the carry flag. | 4642 // If the input is a HeapObject, SmiUntag will set the carry flag. |
| 4679 __ SmiUntag(input_reg, SetCC); | 4643 __ SmiUntag(input_reg, SetCC); |
| 4680 // Branch to deferred code if the input was tagged. | 4644 // Branch to deferred code if the input was tagged. |
| 4681 // The deferred code will take care of restoring the tag. | 4645 // The deferred code will take care of restoring the tag. |
| 4682 __ b(cs, deferred->entry()); | 4646 __ b(cs, deferred->entry()); |
| 4683 __ bind(deferred->exit()); | 4647 __ bind(deferred->exit()); |
| 4684 } | 4648 } |
| 4685 | 4649 |
| 4686 | 4650 |
| 4687 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4651 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 4688 LOperand* input = instr->value(); | 4652 LOperand* input = instr->InputAt(0); |
| 4689 ASSERT(input->IsRegister()); | 4653 ASSERT(input->IsRegister()); |
| 4690 LOperand* result = instr->result(); | 4654 LOperand* result = instr->result(); |
| 4691 ASSERT(result->IsDoubleRegister()); | 4655 ASSERT(result->IsDoubleRegister()); |
| 4692 | 4656 |
| 4693 Register input_reg = ToRegister(input); | 4657 Register input_reg = ToRegister(input); |
| 4694 DoubleRegister result_reg = ToDoubleRegister(result); | 4658 DoubleRegister result_reg = ToDoubleRegister(result); |
| 4695 | 4659 |
| 4696 EmitNumberUntagD(input_reg, result_reg, | 4660 EmitNumberUntagD(input_reg, result_reg, |
| 4697 instr->hydrogen()->deoptimize_on_undefined(), | 4661 instr->hydrogen()->deoptimize_on_undefined(), |
| 4698 instr->hydrogen()->deoptimize_on_minus_zero(), | 4662 instr->hydrogen()->deoptimize_on_minus_zero(), |
| 4699 instr->environment()); | 4663 instr->environment()); |
| 4700 } | 4664 } |
| 4701 | 4665 |
| 4702 | 4666 |
| 4703 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4667 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 4704 Register result_reg = ToRegister(instr->result()); | 4668 Register result_reg = ToRegister(instr->result()); |
| 4705 Register scratch1 = scratch0(); | 4669 Register scratch1 = scratch0(); |
| 4706 Register scratch2 = ToRegister(instr->temp()); | 4670 Register scratch2 = ToRegister(instr->TempAt(0)); |
| 4707 DwVfpRegister double_input = ToDoubleRegister(instr->value()); | 4671 DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0)); |
| 4708 SwVfpRegister single_scratch = double_scratch0().low(); | 4672 SwVfpRegister single_scratch = double_scratch0().low(); |
| 4709 | 4673 |
| 4710 Label done; | 4674 Label done; |
| 4711 | 4675 |
| 4712 if (instr->truncating()) { | 4676 if (instr->truncating()) { |
| 4713 Register scratch3 = ToRegister(instr->temp2()); | 4677 Register scratch3 = ToRegister(instr->TempAt(1)); |
| 4714 __ EmitECMATruncate(result_reg, | 4678 __ EmitECMATruncate(result_reg, |
| 4715 double_input, | 4679 double_input, |
| 4716 single_scratch, | 4680 single_scratch, |
| 4717 scratch1, | 4681 scratch1, |
| 4718 scratch2, | 4682 scratch2, |
| 4719 scratch3); | 4683 scratch3); |
| 4720 } else { | 4684 } else { |
| 4721 VFPRoundingMode rounding_mode = kRoundToMinusInf; | 4685 VFPRoundingMode rounding_mode = kRoundToMinusInf; |
| 4722 __ EmitVFPTruncate(rounding_mode, | 4686 __ EmitVFPTruncate(rounding_mode, |
| 4723 single_scratch, | 4687 single_scratch, |
| 4724 double_input, | 4688 double_input, |
| 4725 scratch1, | 4689 scratch1, |
| 4726 scratch2, | 4690 scratch2, |
| 4727 kCheckForInexactConversion); | 4691 kCheckForInexactConversion); |
| 4728 // Deoptimize if we had a vfp invalid exception, | 4692 // Deoptimize if we had a vfp invalid exception, |
| 4729 // including inexact operation. | 4693 // including inexact operation. |
| 4730 DeoptimizeIf(ne, instr->environment()); | 4694 DeoptimizeIf(ne, instr->environment()); |
| 4731 // Retrieve the result. | 4695 // Retrieve the result. |
| 4732 __ vmov(result_reg, single_scratch); | 4696 __ vmov(result_reg, single_scratch); |
| 4733 } | 4697 } |
| 4734 __ bind(&done); | 4698 __ bind(&done); |
| 4735 } | 4699 } |
| 4736 | 4700 |
| 4737 | 4701 |
| 4738 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 4702 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 4739 LOperand* input = instr->value(); | 4703 LOperand* input = instr->InputAt(0); |
| 4740 __ tst(ToRegister(input), Operand(kSmiTagMask)); | 4704 __ tst(ToRegister(input), Operand(kSmiTagMask)); |
| 4741 DeoptimizeIf(ne, instr->environment()); | 4705 DeoptimizeIf(ne, instr->environment()); |
| 4742 } | 4706 } |
| 4743 | 4707 |
| 4744 | 4708 |
| 4745 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 4709 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
| 4746 LOperand* input = instr->value(); | 4710 LOperand* input = instr->InputAt(0); |
| 4747 __ tst(ToRegister(input), Operand(kSmiTagMask)); | 4711 __ tst(ToRegister(input), Operand(kSmiTagMask)); |
| 4748 DeoptimizeIf(eq, instr->environment()); | 4712 DeoptimizeIf(eq, instr->environment()); |
| 4749 } | 4713 } |
| 4750 | 4714 |
| 4751 | 4715 |
| 4752 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 4716 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 4753 Register input = ToRegister(instr->value()); | 4717 Register input = ToRegister(instr->InputAt(0)); |
| 4754 Register scratch = scratch0(); | 4718 Register scratch = scratch0(); |
| 4755 | 4719 |
| 4756 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 4720 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 4757 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 4721 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 4758 | 4722 |
| 4759 if (instr->hydrogen()->is_interval_check()) { | 4723 if (instr->hydrogen()->is_interval_check()) { |
| 4760 InstanceType first; | 4724 InstanceType first; |
| 4761 InstanceType last; | 4725 InstanceType last; |
| 4762 instr->hydrogen()->GetCheckInterval(&first, &last); | 4726 instr->hydrogen()->GetCheckInterval(&first, &last); |
| 4763 | 4727 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4816 LEnvironment* env) { | 4780 LEnvironment* env) { |
| 4817 Label success; | 4781 Label success; |
| 4818 __ CompareMap(reg, scratch, map, &success, mode); | 4782 __ CompareMap(reg, scratch, map, &success, mode); |
| 4819 DeoptimizeIf(ne, env); | 4783 DeoptimizeIf(ne, env); |
| 4820 __ bind(&success); | 4784 __ bind(&success); |
| 4821 } | 4785 } |
| 4822 | 4786 |
| 4823 | 4787 |
| 4824 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4788 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 4825 Register scratch = scratch0(); | 4789 Register scratch = scratch0(); |
| 4826 LOperand* input = instr->value(); | 4790 LOperand* input = instr->InputAt(0); |
| 4827 ASSERT(input->IsRegister()); | 4791 ASSERT(input->IsRegister()); |
| 4828 Register reg = ToRegister(input); | 4792 Register reg = ToRegister(input); |
| 4829 | 4793 |
| 4830 Label success; | 4794 Label success; |
| 4831 SmallMapList* map_set = instr->hydrogen()->map_set(); | 4795 SmallMapList* map_set = instr->hydrogen()->map_set(); |
| 4832 for (int i = 0; i < map_set->length() - 1; i++) { | 4796 for (int i = 0; i < map_set->length() - 1; i++) { |
| 4833 Handle<Map> map = map_set->at(i); | 4797 Handle<Map> map = map_set->at(i); |
| 4834 __ CompareMap(reg, scratch, map, &success, REQUIRE_EXACT_MAP); | 4798 __ CompareMap(reg, scratch, map, &success, REQUIRE_EXACT_MAP); |
| 4835 __ b(eq, &success); | 4799 __ b(eq, &success); |
| 4836 } | 4800 } |
| 4837 Handle<Map> map = map_set->last(); | 4801 Handle<Map> map = map_set->last(); |
| 4838 DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment()); | 4802 DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment()); |
| 4839 __ bind(&success); | 4803 __ bind(&success); |
| 4840 } | 4804 } |
| 4841 | 4805 |
| 4842 | 4806 |
| 4843 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 4807 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 4844 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); | 4808 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 4845 Register result_reg = ToRegister(instr->result()); | 4809 Register result_reg = ToRegister(instr->result()); |
| 4846 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); | 4810 DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0)); |
| 4847 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); | 4811 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); |
| 4848 } | 4812 } |
| 4849 | 4813 |
| 4850 | 4814 |
| 4851 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 4815 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
| 4852 Register unclamped_reg = ToRegister(instr->unclamped()); | 4816 Register unclamped_reg = ToRegister(instr->unclamped()); |
| 4853 Register result_reg = ToRegister(instr->result()); | 4817 Register result_reg = ToRegister(instr->result()); |
| 4854 __ ClampUint8(result_reg, unclamped_reg); | 4818 __ ClampUint8(result_reg, unclamped_reg); |
| 4855 } | 4819 } |
| 4856 | 4820 |
| 4857 | 4821 |
| 4858 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 4822 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
| 4859 Register scratch = scratch0(); | 4823 Register scratch = scratch0(); |
| 4860 Register input_reg = ToRegister(instr->unclamped()); | 4824 Register input_reg = ToRegister(instr->unclamped()); |
| 4861 Register result_reg = ToRegister(instr->result()); | 4825 Register result_reg = ToRegister(instr->result()); |
| 4862 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); | 4826 DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0)); |
| 4863 Label is_smi, done, heap_number; | 4827 Label is_smi, done, heap_number; |
| 4864 | 4828 |
| 4865 // Both smi and heap number cases are handled. | 4829 // Both smi and heap number cases are handled. |
| 4866 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); | 4830 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); |
| 4867 | 4831 |
| 4868 // Check for heap number | 4832 // Check for heap number |
| 4869 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4833 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4870 __ cmp(scratch, Operand(factory()->heap_number_map())); | 4834 __ cmp(scratch, Operand(factory()->heap_number_map())); |
| 4871 __ b(eq, &heap_number); | 4835 __ b(eq, &heap_number); |
| 4872 | 4836 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4886 | 4850 |
| 4887 // smi | 4851 // smi |
| 4888 __ bind(&is_smi); | 4852 __ bind(&is_smi); |
| 4889 __ ClampUint8(result_reg, result_reg); | 4853 __ ClampUint8(result_reg, result_reg); |
| 4890 | 4854 |
| 4891 __ bind(&done); | 4855 __ bind(&done); |
| 4892 } | 4856 } |
| 4893 | 4857 |
| 4894 | 4858 |
| 4895 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 4859 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 4896 Register temp1 = ToRegister(instr->temp()); | 4860 Register temp1 = ToRegister(instr->TempAt(0)); |
| 4897 Register temp2 = ToRegister(instr->temp2()); | 4861 Register temp2 = ToRegister(instr->TempAt(1)); |
| 4898 | 4862 |
| 4899 Handle<JSObject> holder = instr->holder(); | 4863 Handle<JSObject> holder = instr->holder(); |
| 4900 Handle<JSObject> current_prototype = instr->prototype(); | 4864 Handle<JSObject> current_prototype = instr->prototype(); |
| 4901 | 4865 |
| 4902 // Load prototype object. | 4866 // Load prototype object. |
| 4903 __ LoadHeapObject(temp1, current_prototype); | 4867 __ LoadHeapObject(temp1, current_prototype); |
| 4904 | 4868 |
| 4905 // Check prototype maps up to the holder. | 4869 // Check prototype maps up to the holder. |
| 4906 while (!current_prototype.is_identical_to(holder)) { | 4870 while (!current_prototype.is_identical_to(holder)) { |
| 4907 DoCheckMapCommon(temp1, temp2, | 4871 DoCheckMapCommon(temp1, temp2, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4929 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } | 4893 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } |
| 4930 virtual LInstruction* instr() { return instr_; } | 4894 virtual LInstruction* instr() { return instr_; } |
| 4931 private: | 4895 private: |
| 4932 LAllocateObject* instr_; | 4896 LAllocateObject* instr_; |
| 4933 }; | 4897 }; |
| 4934 | 4898 |
| 4935 DeferredAllocateObject* deferred = | 4899 DeferredAllocateObject* deferred = |
| 4936 new(zone()) DeferredAllocateObject(this, instr); | 4900 new(zone()) DeferredAllocateObject(this, instr); |
| 4937 | 4901 |
| 4938 Register result = ToRegister(instr->result()); | 4902 Register result = ToRegister(instr->result()); |
| 4939 Register scratch = ToRegister(instr->temp()); | 4903 Register scratch = ToRegister(instr->TempAt(0)); |
| 4940 Register scratch2 = ToRegister(instr->temp2()); | 4904 Register scratch2 = ToRegister(instr->TempAt(1)); |
| 4941 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); | 4905 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); |
| 4942 Handle<Map> initial_map(constructor->initial_map()); | 4906 Handle<Map> initial_map(constructor->initial_map()); |
| 4943 int instance_size = initial_map->instance_size(); | 4907 int instance_size = initial_map->instance_size(); |
| 4944 ASSERT(initial_map->pre_allocated_property_fields() + | 4908 ASSERT(initial_map->pre_allocated_property_fields() + |
| 4945 initial_map->unused_property_fields() - | 4909 initial_map->unused_property_fields() - |
| 4946 initial_map->inobject_properties() == 0); | 4910 initial_map->inobject_properties() == 0); |
| 4947 | 4911 |
| 4948 // Allocate memory for the object. The initial map might change when | 4912 // Allocate memory for the object. The initial map might change when |
| 4949 // the constructor's prototype changes, but instance size and property | 4913 // the constructor's prototype changes, but instance size and property |
| 4950 // counts remain unchanged (if slack tracking finished). | 4914 // counts remain unchanged (if slack tracking finished). |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5222 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 5186 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
| 5223 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); | 5187 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); |
| 5224 } else { | 5188 } else { |
| 5225 FastCloneShallowObjectStub stub(properties_count); | 5189 FastCloneShallowObjectStub stub(properties_count); |
| 5226 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 5190 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 5227 } | 5191 } |
| 5228 } | 5192 } |
| 5229 | 5193 |
| 5230 | 5194 |
| 5231 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5195 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
| 5232 ASSERT(ToRegister(instr->value()).is(r0)); | 5196 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); |
| 5233 __ push(r0); | 5197 __ push(r0); |
| 5234 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5198 CallRuntime(Runtime::kToFastProperties, 1, instr); |
| 5235 } | 5199 } |
| 5236 | 5200 |
| 5237 | 5201 |
| 5238 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5202 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| 5239 Label materialized; | 5203 Label materialized; |
| 5240 // Registers will be used as follows: | 5204 // Registers will be used as follows: |
| 5241 // r7 = literals array. | 5205 // r7 = literals array. |
| 5242 // r1 = regexp literal. | 5206 // r1 = regexp literal. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5303 __ mov(r1, Operand(pretenure | 5267 __ mov(r1, Operand(pretenure |
| 5304 ? factory()->true_value() | 5268 ? factory()->true_value() |
| 5305 : factory()->false_value())); | 5269 : factory()->false_value())); |
| 5306 __ Push(cp, r2, r1); | 5270 __ Push(cp, r2, r1); |
| 5307 CallRuntime(Runtime::kNewClosure, 3, instr); | 5271 CallRuntime(Runtime::kNewClosure, 3, instr); |
| 5308 } | 5272 } |
| 5309 } | 5273 } |
| 5310 | 5274 |
| 5311 | 5275 |
| 5312 void LCodeGen::DoTypeof(LTypeof* instr) { | 5276 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 5313 Register input = ToRegister(instr->value()); | 5277 Register input = ToRegister(instr->InputAt(0)); |
| 5314 __ push(input); | 5278 __ push(input); |
| 5315 CallRuntime(Runtime::kTypeof, 1, instr); | 5279 CallRuntime(Runtime::kTypeof, 1, instr); |
| 5316 } | 5280 } |
| 5317 | 5281 |
| 5318 | 5282 |
| 5319 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5283 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 5320 Register input = ToRegister(instr->value()); | 5284 Register input = ToRegister(instr->InputAt(0)); |
| 5321 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 5285 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 5322 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 5286 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 5323 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 5287 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 5324 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 5288 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 5325 | 5289 |
| 5326 Condition final_branch_condition = EmitTypeofIs(true_label, | 5290 Condition final_branch_condition = EmitTypeofIs(true_label, |
| 5327 false_label, | 5291 false_label, |
| 5328 input, | 5292 input, |
| 5329 instr->type_literal()); | 5293 instr->type_literal()); |
| 5330 if (final_branch_condition != kNoCondition) { | 5294 if (final_branch_condition != kNoCondition) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5400 | 5364 |
| 5401 } else { | 5365 } else { |
| 5402 __ b(false_label); | 5366 __ b(false_label); |
| 5403 } | 5367 } |
| 5404 | 5368 |
| 5405 return final_branch_condition; | 5369 return final_branch_condition; |
| 5406 } | 5370 } |
| 5407 | 5371 |
| 5408 | 5372 |
| 5409 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 5373 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 5410 Register temp1 = ToRegister(instr->temp()); | 5374 Register temp1 = ToRegister(instr->TempAt(0)); |
| 5411 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 5375 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 5412 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 5376 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 5413 | 5377 |
| 5414 EmitIsConstructCall(temp1, scratch0()); | 5378 EmitIsConstructCall(temp1, scratch0()); |
| 5415 EmitBranch(true_block, false_block, eq); | 5379 EmitBranch(true_block, false_block, eq); |
| 5416 } | 5380 } |
| 5417 | 5381 |
| 5418 | 5382 |
| 5419 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { | 5383 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { |
| 5420 ASSERT(!temp1.is(temp2)); | 5384 ASSERT(!temp1.is(temp2)); |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5660 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 5624 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 5661 __ ldr(result, FieldMemOperand(scratch, | 5625 __ ldr(result, FieldMemOperand(scratch, |
| 5662 FixedArray::kHeaderSize - kPointerSize)); | 5626 FixedArray::kHeaderSize - kPointerSize)); |
| 5663 __ bind(&done); | 5627 __ bind(&done); |
| 5664 } | 5628 } |
| 5665 | 5629 |
| 5666 | 5630 |
| 5667 #undef __ | 5631 #undef __ |
| 5668 | 5632 |
| 5669 } } // namespace v8::internal | 5633 } } // namespace v8::internal |
| OLD | NEW |