| 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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 #ifdef _MSC_VER | 123 #ifdef _MSC_VER |
| 124 void LCodeGen::MakeSureStackPagesMapped(int offset) { | 124 void LCodeGen::MakeSureStackPagesMapped(int offset) { |
| 125 const int kPageSize = 4 * KB; | 125 const int kPageSize = 4 * KB; |
| 126 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { | 126 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { |
| 127 __ mov(Operand(esp, offset), eax); | 127 __ mov(Operand(esp, offset), eax); |
| 128 } | 128 } |
| 129 } | 129 } |
| 130 #endif | 130 #endif |
| 131 | 131 |
| 132 | 132 |
| 133 void LCodeGen::SaveCallerDoubles() { |
| 134 ASSERT(info()->saves_caller_doubles()); |
| 135 ASSERT(NeedsEagerFrame()); |
| 136 Comment(";;; Save clobbered callee double registers"); |
| 137 CpuFeatureScope scope(masm(), SSE2); |
| 138 int count = 0; |
| 139 BitVector* doubles = chunk()->allocated_double_registers(); |
| 140 BitVector::Iterator save_iterator(doubles); |
| 141 while (!save_iterator.Done()) { |
| 142 __ movsd(MemOperand(esp, count * kDoubleSize), |
| 143 XMMRegister::FromAllocationIndex(save_iterator.Current())); |
| 144 save_iterator.Advance(); |
| 145 count++; |
| 146 } |
| 147 } |
| 148 |
| 149 |
| 150 void LCodeGen::RestoreCallerDoubles() { |
| 151 ASSERT(info()->saves_caller_doubles()); |
| 152 ASSERT(NeedsEagerFrame()); |
| 153 Comment(";;; Restore clobbered callee double registers"); |
| 154 CpuFeatureScope scope(masm(), SSE2); |
| 155 BitVector* doubles = chunk()->allocated_double_registers(); |
| 156 BitVector::Iterator save_iterator(doubles); |
| 157 int count = 0; |
| 158 while (!save_iterator.Done()) { |
| 159 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), |
| 160 MemOperand(esp, count * kDoubleSize)); |
| 161 save_iterator.Advance(); |
| 162 count++; |
| 163 } |
| 164 } |
| 165 |
| 166 |
| 133 bool LCodeGen::GeneratePrologue() { | 167 bool LCodeGen::GeneratePrologue() { |
| 134 ASSERT(is_generating()); | 168 ASSERT(is_generating()); |
| 135 | 169 |
| 136 if (info()->IsOptimizing()) { | 170 if (info()->IsOptimizing()) { |
| 137 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 171 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 138 | 172 |
| 139 #ifdef DEBUG | 173 #ifdef DEBUG |
| 140 if (strlen(FLAG_stop_at) > 0 && | 174 if (strlen(FLAG_stop_at) > 0 && |
| 141 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 175 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 142 __ int3(); | 176 __ int3(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 153 __ j(zero, &ok, Label::kNear); | 187 __ j(zero, &ok, Label::kNear); |
| 154 // +1 for return address. | 188 // +1 for return address. |
| 155 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; | 189 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; |
| 156 __ mov(Operand(esp, receiver_offset), | 190 __ mov(Operand(esp, receiver_offset), |
| 157 Immediate(isolate()->factory()->undefined_value())); | 191 Immediate(isolate()->factory()->undefined_value())); |
| 158 __ bind(&ok); | 192 __ bind(&ok); |
| 159 } | 193 } |
| 160 | 194 |
| 161 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { | 195 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { |
| 162 // Move state of dynamic frame alignment into edx. | 196 // Move state of dynamic frame alignment into edx. |
| 163 __ mov(edx, Immediate(kNoAlignmentPadding)); | 197 __ Set(edx, Immediate(kNoAlignmentPadding)); |
| 164 | 198 |
| 165 Label do_not_pad, align_loop; | 199 Label do_not_pad, align_loop; |
| 166 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); | 200 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); |
| 167 // Align esp + 4 to a multiple of 2 * kPointerSize. | 201 // Align esp + 4 to a multiple of 2 * kPointerSize. |
| 168 __ test(esp, Immediate(kPointerSize)); | 202 __ test(esp, Immediate(kPointerSize)); |
| 169 __ j(not_zero, &do_not_pad, Label::kNear); | 203 __ j(not_zero, &do_not_pad, Label::kNear); |
| 170 __ push(Immediate(0)); | 204 __ push(Immediate(0)); |
| 171 __ mov(ebx, esp); | 205 __ mov(ebx, esp); |
| 172 __ mov(edx, Immediate(kAlignmentPaddingPushed)); | 206 __ mov(edx, Immediate(kAlignmentPaddingPushed)); |
| 173 // Copy arguments, receiver, and return address. | 207 // Copy arguments, receiver, and return address. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset; | 271 int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset; |
| 238 if (dynamic_frame_alignment_) { | 272 if (dynamic_frame_alignment_) { |
| 239 __ mov(Operand(ebp, offset), edx); | 273 __ mov(Operand(ebp, offset), edx); |
| 240 } else { | 274 } else { |
| 241 __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding)); | 275 __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding)); |
| 242 } | 276 } |
| 243 } | 277 } |
| 244 } | 278 } |
| 245 | 279 |
| 246 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { | 280 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { |
| 247 Comment(";;; Save clobbered callee double registers"); | 281 SaveCallerDoubles(); |
| 248 CpuFeatureScope scope(masm(), SSE2); | |
| 249 int count = 0; | |
| 250 BitVector* doubles = chunk()->allocated_double_registers(); | |
| 251 BitVector::Iterator save_iterator(doubles); | |
| 252 while (!save_iterator.Done()) { | |
| 253 __ movsd(MemOperand(esp, count * kDoubleSize), | |
| 254 XMMRegister::FromAllocationIndex(save_iterator.Current())); | |
| 255 save_iterator.Advance(); | |
| 256 count++; | |
| 257 } | |
| 258 } | 282 } |
| 259 } | 283 } |
| 260 | 284 |
| 261 // Possibly allocate a local context. | 285 // Possibly allocate a local context. |
| 262 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 286 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 263 if (heap_slots > 0) { | 287 if (heap_slots > 0) { |
| 264 Comment(";;; Allocate local context"); | 288 Comment(";;; Allocate local context"); |
| 265 // Argument to NewContext is the function, which is still in edi. | 289 // Argument to NewContext is the function, which is still in edi. |
| 266 __ push(edi); | 290 __ push(edi); |
| 267 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 291 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 | 333 |
| 310 | 334 |
| 311 void LCodeGen::GenerateOsrPrologue() { | 335 void LCodeGen::GenerateOsrPrologue() { |
| 312 // Generate the OSR entry prologue at the first unknown OSR value, or if there | 336 // Generate the OSR entry prologue at the first unknown OSR value, or if there |
| 313 // are none, at the OSR entrypoint instruction. | 337 // are none, at the OSR entrypoint instruction. |
| 314 if (osr_pc_offset_ >= 0) return; | 338 if (osr_pc_offset_ >= 0) return; |
| 315 | 339 |
| 316 osr_pc_offset_ = masm()->pc_offset(); | 340 osr_pc_offset_ = masm()->pc_offset(); |
| 317 | 341 |
| 318 // Move state of dynamic frame alignment into edx. | 342 // Move state of dynamic frame alignment into edx. |
| 319 __ mov(edx, Immediate(kNoAlignmentPadding)); | 343 __ Set(edx, Immediate(kNoAlignmentPadding)); |
| 320 | 344 |
| 321 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { | 345 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { |
| 322 Label do_not_pad, align_loop; | 346 Label do_not_pad, align_loop; |
| 323 // Align ebp + 4 to a multiple of 2 * kPointerSize. | 347 // Align ebp + 4 to a multiple of 2 * kPointerSize. |
| 324 __ test(ebp, Immediate(kPointerSize)); | 348 __ test(ebp, Immediate(kPointerSize)); |
| 325 __ j(zero, &do_not_pad, Label::kNear); | 349 __ j(zero, &do_not_pad, Label::kNear); |
| 326 __ push(Immediate(0)); | 350 __ push(Immediate(0)); |
| 327 __ mov(ebx, esp); | 351 __ mov(ebx, esp); |
| 328 __ mov(edx, Immediate(kAlignmentPaddingPushed)); | 352 __ mov(edx, Immediate(kAlignmentPaddingPushed)); |
| 329 | 353 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 __ bind(&jump_table_[i].label); | 416 __ bind(&jump_table_[i].label); |
| 393 Address entry = jump_table_[i].address; | 417 Address entry = jump_table_[i].address; |
| 394 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; | 418 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; |
| 395 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 419 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
| 396 if (id == Deoptimizer::kNotDeoptimizationEntry) { | 420 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
| 397 Comment(";;; jump table entry %d.", i); | 421 Comment(";;; jump table entry %d.", i); |
| 398 } else { | 422 } else { |
| 399 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 423 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
| 400 } | 424 } |
| 401 if (jump_table_[i].needs_frame) { | 425 if (jump_table_[i].needs_frame) { |
| 426 ASSERT(!info()->saves_caller_doubles()); |
| 402 __ push(Immediate(ExternalReference::ForDeoptEntry(entry))); | 427 __ push(Immediate(ExternalReference::ForDeoptEntry(entry))); |
| 403 if (needs_frame.is_bound()) { | 428 if (needs_frame.is_bound()) { |
| 404 __ jmp(&needs_frame); | 429 __ jmp(&needs_frame); |
| 405 } else { | 430 } else { |
| 406 __ bind(&needs_frame); | 431 __ bind(&needs_frame); |
| 407 __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset)); | 432 __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset)); |
| 408 // This variant of deopt can only be used with stubs. Since we don't | 433 // This variant of deopt can only be used with stubs. Since we don't |
| 409 // have a function pointer to install in the stack frame that we're | 434 // have a function pointer to install in the stack frame that we're |
| 410 // building, install a special marker there instead. | 435 // building, install a special marker there instead. |
| 411 ASSERT(info()->IsStub()); | 436 ASSERT(info()->IsStub()); |
| 412 __ push(Immediate(Smi::FromInt(StackFrame::STUB))); | 437 __ push(Immediate(Smi::FromInt(StackFrame::STUB))); |
| 413 // Push a PC inside the function so that the deopt code can find where | 438 // Push a PC inside the function so that the deopt code can find where |
| 414 // the deopt comes from. It doesn't have to be the precise return | 439 // the deopt comes from. It doesn't have to be the precise return |
| 415 // address of a "calling" LAZY deopt, it only has to be somewhere | 440 // address of a "calling" LAZY deopt, it only has to be somewhere |
| 416 // inside the code body. | 441 // inside the code body. |
| 417 Label push_approx_pc; | 442 Label push_approx_pc; |
| 418 __ call(&push_approx_pc); | 443 __ call(&push_approx_pc); |
| 419 __ bind(&push_approx_pc); | 444 __ bind(&push_approx_pc); |
| 420 // Push the continuation which was stashed were the ebp should | 445 // Push the continuation which was stashed were the ebp should |
| 421 // be. Replace it with the saved ebp. | 446 // be. Replace it with the saved ebp. |
| 422 __ push(MemOperand(esp, 3 * kPointerSize)); | 447 __ push(MemOperand(esp, 3 * kPointerSize)); |
| 423 __ mov(MemOperand(esp, 4 * kPointerSize), ebp); | 448 __ mov(MemOperand(esp, 4 * kPointerSize), ebp); |
| 424 __ lea(ebp, MemOperand(esp, 4 * kPointerSize)); | 449 __ lea(ebp, MemOperand(esp, 4 * kPointerSize)); |
| 425 __ ret(0); // Call the continuation without clobbering registers. | 450 __ ret(0); // Call the continuation without clobbering registers. |
| 426 } | 451 } |
| 427 } else { | 452 } else { |
| 453 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { |
| 454 RestoreCallerDoubles(); |
| 455 } |
| 428 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 456 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
| 429 } | 457 } |
| 430 } | 458 } |
| 431 return !is_aborted(); | 459 return !is_aborted(); |
| 432 } | 460 } |
| 433 | 461 |
| 434 | 462 |
| 435 bool LCodeGen::GenerateDeferredCode() { | 463 bool LCodeGen::GenerateDeferredCode() { |
| 436 ASSERT(is_generating()); | 464 ASSERT(is_generating()); |
| 437 if (deferred_.length() > 0) { | 465 if (deferred_.length() > 0) { |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 bool LCodeGen::IsInteger32(LConstantOperand* op) const { | 802 bool LCodeGen::IsInteger32(LConstantOperand* op) const { |
| 775 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); | 803 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); |
| 776 } | 804 } |
| 777 | 805 |
| 778 | 806 |
| 779 bool LCodeGen::IsSmi(LConstantOperand* op) const { | 807 bool LCodeGen::IsSmi(LConstantOperand* op) const { |
| 780 return chunk_->LookupLiteralRepresentation(op).IsSmi(); | 808 return chunk_->LookupLiteralRepresentation(op).IsSmi(); |
| 781 } | 809 } |
| 782 | 810 |
| 783 | 811 |
| 812 static int ArgumentsOffsetWithoutFrame(int index) { |
| 813 ASSERT(index < 0); |
| 814 return -(index + 1) * kPointerSize + kPCOnStackSize; |
| 815 } |
| 816 |
| 817 |
| 784 Operand LCodeGen::ToOperand(LOperand* op) const { | 818 Operand LCodeGen::ToOperand(LOperand* op) const { |
| 785 if (op->IsRegister()) return Operand(ToRegister(op)); | 819 if (op->IsRegister()) return Operand(ToRegister(op)); |
| 786 if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op)); | 820 if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op)); |
| 787 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); | 821 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); |
| 788 return Operand(ebp, StackSlotOffset(op->index())); | 822 if (NeedsEagerFrame()) { |
| 823 return Operand(ebp, StackSlotOffset(op->index())); |
| 824 } else { |
| 825 // Retrieve parameter without eager stack-frame relative to the |
| 826 // stack-pointer. |
| 827 return Operand(esp, ArgumentsOffsetWithoutFrame(op->index())); |
| 828 } |
| 789 } | 829 } |
| 790 | 830 |
| 791 | 831 |
| 792 Operand LCodeGen::HighOperand(LOperand* op) { | 832 Operand LCodeGen::HighOperand(LOperand* op) { |
| 793 ASSERT(op->IsDoubleStackSlot()); | 833 ASSERT(op->IsDoubleStackSlot()); |
| 794 return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize); | 834 if (NeedsEagerFrame()) { |
| 835 return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize); |
| 836 } else { |
| 837 // Retrieve parameter without eager stack-frame relative to the |
| 838 // stack-pointer. |
| 839 return Operand( |
| 840 esp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize); |
| 841 } |
| 795 } | 842 } |
| 796 | 843 |
| 797 | 844 |
| 798 void LCodeGen::WriteTranslation(LEnvironment* environment, | 845 void LCodeGen::WriteTranslation(LEnvironment* environment, |
| 799 Translation* translation) { | 846 Translation* translation) { |
| 800 if (environment == NULL) return; | 847 if (environment == NULL) return; |
| 801 | 848 |
| 802 // The translation includes one command per value in the environment. | 849 // The translation includes one command per value in the environment. |
| 803 int translation_size = environment->translation_size(); | 850 int translation_size = environment->translation_size(); |
| 804 // The output frame height does not include the parameters. | 851 // The output frame height does not include the parameters. |
| (...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1373 __ neg(left_reg); | 1420 __ neg(left_reg); |
| 1374 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1421 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1375 DeoptimizeIf(zero, instr->environment()); | 1422 DeoptimizeIf(zero, instr->environment()); |
| 1376 } | 1423 } |
| 1377 __ jmp(&done, Label::kNear); | 1424 __ jmp(&done, Label::kNear); |
| 1378 } | 1425 } |
| 1379 | 1426 |
| 1380 __ bind(&left_is_not_negative); | 1427 __ bind(&left_is_not_negative); |
| 1381 __ and_(left_reg, divisor - 1); | 1428 __ and_(left_reg, divisor - 1); |
| 1382 __ bind(&done); | 1429 __ bind(&done); |
| 1383 | |
| 1384 } else if (hmod->fixed_right_arg().has_value) { | |
| 1385 Register left_reg = ToRegister(instr->left()); | |
| 1386 ASSERT(left_reg.is(ToRegister(instr->result()))); | |
| 1387 Register right_reg = ToRegister(instr->right()); | |
| 1388 | |
| 1389 int32_t divisor = hmod->fixed_right_arg().value; | |
| 1390 ASSERT(IsPowerOf2(divisor)); | |
| 1391 | |
| 1392 // Check if our assumption of a fixed right operand still holds. | |
| 1393 __ cmp(right_reg, Immediate(divisor)); | |
| 1394 DeoptimizeIf(not_equal, instr->environment()); | |
| 1395 | |
| 1396 Label left_is_not_negative, done; | |
| 1397 if (left->CanBeNegative()) { | |
| 1398 __ test(left_reg, Operand(left_reg)); | |
| 1399 __ j(not_sign, &left_is_not_negative, Label::kNear); | |
| 1400 __ neg(left_reg); | |
| 1401 __ and_(left_reg, divisor - 1); | |
| 1402 __ neg(left_reg); | |
| 1403 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
| 1404 DeoptimizeIf(zero, instr->environment()); | |
| 1405 } | |
| 1406 __ jmp(&done, Label::kNear); | |
| 1407 } | |
| 1408 | |
| 1409 __ bind(&left_is_not_negative); | |
| 1410 __ and_(left_reg, divisor - 1); | |
| 1411 __ bind(&done); | |
| 1412 | |
| 1413 } else { | 1430 } else { |
| 1414 Register left_reg = ToRegister(instr->left()); | 1431 Register left_reg = ToRegister(instr->left()); |
| 1415 ASSERT(left_reg.is(eax)); | 1432 ASSERT(left_reg.is(eax)); |
| 1416 Register right_reg = ToRegister(instr->right()); | 1433 Register right_reg = ToRegister(instr->right()); |
| 1417 ASSERT(!right_reg.is(eax)); | 1434 ASSERT(!right_reg.is(eax)); |
| 1418 ASSERT(!right_reg.is(edx)); | 1435 ASSERT(!right_reg.is(edx)); |
| 1419 Register result_reg = ToRegister(instr->result()); | 1436 Register result_reg = ToRegister(instr->result()); |
| 1420 ASSERT(result_reg.is(edx)); | 1437 ASSERT(result_reg.is(edx)); |
| 1421 | 1438 |
| 1422 Label done; | 1439 Label done; |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2104 __ movzx_w(result, operand); | 2121 __ movzx_w(result, operand); |
| 2105 } | 2122 } |
| 2106 } | 2123 } |
| 2107 | 2124 |
| 2108 | 2125 |
| 2109 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { | 2126 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { |
| 2110 String::Encoding encoding = instr->hydrogen()->encoding(); | 2127 String::Encoding encoding = instr->hydrogen()->encoding(); |
| 2111 Register string = ToRegister(instr->string()); | 2128 Register string = ToRegister(instr->string()); |
| 2112 | 2129 |
| 2113 if (FLAG_debug_code) { | 2130 if (FLAG_debug_code) { |
| 2114 __ push(string); | 2131 Register value = ToRegister(instr->value()); |
| 2115 __ mov(string, FieldOperand(string, HeapObject::kMapOffset)); | 2132 Register index = ToRegister(instr->index()); |
| 2116 __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset)); | |
| 2117 | |
| 2118 __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); | |
| 2119 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 2133 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
| 2120 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 2134 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 2121 __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING | 2135 int encoding_mask = |
| 2122 ? one_byte_seq_type : two_byte_seq_type)); | 2136 instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING |
| 2123 __ Check(equal, kUnexpectedStringType); | 2137 ? one_byte_seq_type : two_byte_seq_type; |
| 2124 __ pop(string); | 2138 __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask); |
| 2125 } | 2139 } |
| 2126 | 2140 |
| 2127 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); | 2141 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
| 2128 if (instr->value()->IsConstantOperand()) { | 2142 if (instr->value()->IsConstantOperand()) { |
| 2129 int value = ToRepresentation(LConstantOperand::cast(instr->value()), | 2143 int value = ToRepresentation(LConstantOperand::cast(instr->value()), |
| 2130 Representation::Integer32()); | 2144 Representation::Integer32()); |
| 2131 ASSERT_LE(0, value); | 2145 ASSERT_LE(0, value); |
| 2132 if (encoding == String::ONE_BYTE_ENCODING) { | 2146 if (encoding == String::ONE_BYTE_ENCODING) { |
| 2133 ASSERT_LE(value, String::kMaxOneByteCharCode); | 2147 ASSERT_LE(value, String::kMaxOneByteCharCode); |
| 2134 __ mov_b(operand, static_cast<int8_t>(value)); | 2148 __ mov_b(operand, static_cast<int8_t>(value)); |
| (...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3136 if (FLAG_trace && info()->IsOptimizing()) { | 3150 if (FLAG_trace && info()->IsOptimizing()) { |
| 3137 // Preserve the return value on the stack and rely on the runtime call | 3151 // Preserve the return value on the stack and rely on the runtime call |
| 3138 // to return the value in the same register. We're leaving the code | 3152 // to return the value in the same register. We're leaving the code |
| 3139 // managed by the register allocator and tearing down the frame, it's | 3153 // managed by the register allocator and tearing down the frame, it's |
| 3140 // safe to write to the context register. | 3154 // safe to write to the context register. |
| 3141 __ push(eax); | 3155 __ push(eax); |
| 3142 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3156 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3143 __ CallRuntime(Runtime::kTraceExit, 1); | 3157 __ CallRuntime(Runtime::kTraceExit, 1); |
| 3144 } | 3158 } |
| 3145 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { | 3159 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { |
| 3146 ASSERT(NeedsEagerFrame()); | 3160 RestoreCallerDoubles(); |
| 3147 CpuFeatureScope scope(masm(), SSE2); | |
| 3148 BitVector* doubles = chunk()->allocated_double_registers(); | |
| 3149 BitVector::Iterator save_iterator(doubles); | |
| 3150 int count = 0; | |
| 3151 while (!save_iterator.Done()) { | |
| 3152 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), | |
| 3153 MemOperand(esp, count * kDoubleSize)); | |
| 3154 save_iterator.Advance(); | |
| 3155 count++; | |
| 3156 } | |
| 3157 } | 3161 } |
| 3158 if (dynamic_frame_alignment_) { | 3162 if (dynamic_frame_alignment_) { |
| 3159 // Fetch the state of the dynamic frame alignment. | 3163 // Fetch the state of the dynamic frame alignment. |
| 3160 __ mov(edx, Operand(ebp, | 3164 __ mov(edx, Operand(ebp, |
| 3161 JavaScriptFrameConstants::kDynamicAlignmentStateOffset)); | 3165 JavaScriptFrameConstants::kDynamicAlignmentStateOffset)); |
| 3162 } | 3166 } |
| 3163 int no_frame_start = -1; | 3167 int no_frame_start = -1; |
| 3164 if (NeedsEagerFrame()) { | 3168 if (NeedsEagerFrame()) { |
| 3165 __ mov(esp, ebp); | 3169 __ mov(esp, ebp); |
| 3166 __ pop(ebp); | 3170 __ pop(ebp); |
| (...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4174 MathPowStub stub(MathPowStub::INTEGER); | 4178 MathPowStub stub(MathPowStub::INTEGER); |
| 4175 __ CallStub(&stub); | 4179 __ CallStub(&stub); |
| 4176 } else { | 4180 } else { |
| 4177 ASSERT(exponent_type.IsDouble()); | 4181 ASSERT(exponent_type.IsDouble()); |
| 4178 MathPowStub stub(MathPowStub::DOUBLE); | 4182 MathPowStub stub(MathPowStub::DOUBLE); |
| 4179 __ CallStub(&stub); | 4183 __ CallStub(&stub); |
| 4180 } | 4184 } |
| 4181 } | 4185 } |
| 4182 | 4186 |
| 4183 | 4187 |
| 4184 void LCodeGen::DoRandom(LRandom* instr) { | |
| 4185 CpuFeatureScope scope(masm(), SSE2); | |
| 4186 | |
| 4187 // Assert that the register size is indeed the size of each seed. | |
| 4188 static const int kSeedSize = sizeof(uint32_t); | |
| 4189 STATIC_ASSERT(kPointerSize == kSeedSize); | |
| 4190 | |
| 4191 // Load native context | |
| 4192 Register global_object = ToRegister(instr->global_object()); | |
| 4193 Register native_context = global_object; | |
| 4194 __ mov(native_context, FieldOperand( | |
| 4195 global_object, GlobalObject::kNativeContextOffset)); | |
| 4196 | |
| 4197 // Load state (FixedArray of the native context's random seeds) | |
| 4198 static const int kRandomSeedOffset = | |
| 4199 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; | |
| 4200 Register state = native_context; | |
| 4201 __ mov(state, FieldOperand(native_context, kRandomSeedOffset)); | |
| 4202 | |
| 4203 // Load state[0]. | |
| 4204 Register state0 = ToRegister(instr->scratch()); | |
| 4205 __ mov(state0, FieldOperand(state, ByteArray::kHeaderSize)); | |
| 4206 // Load state[1]. | |
| 4207 Register state1 = ToRegister(instr->scratch2()); | |
| 4208 __ mov(state1, FieldOperand(state, ByteArray::kHeaderSize + kSeedSize)); | |
| 4209 | |
| 4210 // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16) | |
| 4211 Register scratch3 = ToRegister(instr->scratch3()); | |
| 4212 __ movzx_w(scratch3, state0); | |
| 4213 __ imul(scratch3, scratch3, 18273); | |
| 4214 __ shr(state0, 16); | |
| 4215 __ add(state0, scratch3); | |
| 4216 // Save state[0]. | |
| 4217 __ mov(FieldOperand(state, ByteArray::kHeaderSize), state0); | |
| 4218 | |
| 4219 // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16) | |
| 4220 __ movzx_w(scratch3, state1); | |
| 4221 __ imul(scratch3, scratch3, 36969); | |
| 4222 __ shr(state1, 16); | |
| 4223 __ add(state1, scratch3); | |
| 4224 // Save state[1]. | |
| 4225 __ mov(FieldOperand(state, ByteArray::kHeaderSize + kSeedSize), state1); | |
| 4226 | |
| 4227 // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF) | |
| 4228 Register random = state0; | |
| 4229 __ shl(random, 14); | |
| 4230 __ and_(state1, Immediate(0x3FFFF)); | |
| 4231 __ add(random, state1); | |
| 4232 | |
| 4233 // Convert 32 random bits in random to 0.(32 random bits) in a double | |
| 4234 // by computing: | |
| 4235 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | |
| 4236 XMMRegister result = ToDoubleRegister(instr->result()); | |
| 4237 XMMRegister scratch4 = double_scratch0(); | |
| 4238 __ mov(scratch3, Immediate(0x49800000)); // 1.0 x 2^20 as single. | |
| 4239 __ movd(scratch4, scratch3); | |
| 4240 __ movd(result, random); | |
| 4241 __ cvtss2sd(scratch4, scratch4); | |
| 4242 __ xorps(result, scratch4); | |
| 4243 __ subsd(result, scratch4); | |
| 4244 } | |
| 4245 | |
| 4246 | |
| 4247 void LCodeGen::DoMathLog(LMathLog* instr) { | 4188 void LCodeGen::DoMathLog(LMathLog* instr) { |
| 4248 CpuFeatureScope scope(masm(), SSE2); | 4189 CpuFeatureScope scope(masm(), SSE2); |
| 4249 ASSERT(instr->value()->Equals(instr->result())); | 4190 ASSERT(instr->value()->Equals(instr->result())); |
| 4250 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 4191 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4251 XMMRegister xmm_scratch = double_scratch0(); | 4192 XMMRegister xmm_scratch = double_scratch0(); |
| 4252 Label positive, done, zero; | 4193 Label positive, done, zero; |
| 4253 __ xorps(xmm_scratch, xmm_scratch); | 4194 __ xorps(xmm_scratch, xmm_scratch); |
| 4254 __ ucomisd(input_reg, xmm_scratch); | 4195 __ ucomisd(input_reg, xmm_scratch); |
| 4255 __ j(above, &positive, Label::kNear); | 4196 __ j(above, &positive, Label::kNear); |
| 4256 __ j(equal, &zero, Label::kNear); | 4197 __ j(equal, &zero, Label::kNear); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4369 } | 4310 } |
| 4370 | 4311 |
| 4371 | 4312 |
| 4372 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4313 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 4373 ASSERT(ToRegister(instr->context()).is(esi)); | 4314 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4374 ASSERT(ToRegister(instr->function()).is(edi)); | 4315 ASSERT(ToRegister(instr->function()).is(edi)); |
| 4375 ASSERT(ToRegister(instr->result()).is(eax)); | 4316 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4376 | 4317 |
| 4377 int arity = instr->arity(); | 4318 int arity = instr->arity(); |
| 4378 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 4319 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
| 4379 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4320 if (instr->hydrogen()->IsTailCall()) { |
| 4321 if (NeedsEagerFrame()) __ leave(); |
| 4322 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
| 4323 } else { |
| 4324 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4325 } |
| 4380 } | 4326 } |
| 4381 | 4327 |
| 4382 | 4328 |
| 4383 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 4329 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| 4384 ASSERT(ToRegister(instr->context()).is(esi)); | 4330 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4385 ASSERT(ToRegister(instr->result()).is(eax)); | 4331 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4386 | 4332 |
| 4387 int arity = instr->arity(); | 4333 int arity = instr->arity(); |
| 4388 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 4334 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
| 4389 Handle<Code> ic = | 4335 Handle<Code> ic = |
| (...skipping 1635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6025 } | 5971 } |
| 6026 } | 5972 } |
| 6027 | 5973 |
| 6028 | 5974 |
| 6029 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { | 5975 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { |
| 6030 Register result = ToRegister(instr->result()); | 5976 Register result = ToRegister(instr->result()); |
| 6031 | 5977 |
| 6032 // TODO(3095996): Get rid of this. For now, we need to make the | 5978 // TODO(3095996): Get rid of this. For now, we need to make the |
| 6033 // result register contain a valid pointer because it is already | 5979 // result register contain a valid pointer because it is already |
| 6034 // contained in the register pointer map. | 5980 // contained in the register pointer map. |
| 6035 __ mov(result, Immediate(Smi::FromInt(0))); | 5981 __ Set(result, Immediate(Smi::FromInt(0))); |
| 6036 | 5982 |
| 6037 PushSafepointRegistersScope scope(this); | 5983 PushSafepointRegistersScope scope(this); |
| 6038 if (instr->size()->IsRegister()) { | 5984 if (instr->size()->IsRegister()) { |
| 6039 Register size = ToRegister(instr->size()); | 5985 Register size = ToRegister(instr->size()); |
| 6040 ASSERT(!size.is(result)); | 5986 ASSERT(!size.is(result)); |
| 6041 __ SmiTag(ToRegister(instr->size())); | 5987 __ SmiTag(ToRegister(instr->size())); |
| 6042 __ push(size); | 5988 __ push(size); |
| 6043 } else { | 5989 } else { |
| 6044 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5990 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 6045 __ push(Immediate(Smi::FromInt(size))); | 5991 __ push(Immediate(Smi::FromInt(size))); |
| 6046 } | 5992 } |
| 6047 | 5993 |
| 5994 int flags = AllocateDoubleAlignFlag::encode( |
| 5995 instr->hydrogen()->MustAllocateDoubleAligned()); |
| 6048 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5996 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
| 6049 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5997 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 6050 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5998 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 6051 CallRuntimeFromDeferred( | 5999 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); |
| 6052 Runtime::kAllocateInOldPointerSpace, 1, instr, instr->context()); | |
| 6053 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 6000 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 6054 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 6001 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 6055 CallRuntimeFromDeferred( | 6002 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); |
| 6056 Runtime::kAllocateInOldDataSpace, 1, instr, instr->context()); | |
| 6057 } else { | 6003 } else { |
| 6058 CallRuntimeFromDeferred( | 6004 flags = AllocateTargetSpace::update(flags, NEW_SPACE); |
| 6059 Runtime::kAllocateInNewSpace, 1, instr, instr->context()); | |
| 6060 } | 6005 } |
| 6006 __ push(Immediate(Smi::FromInt(flags))); |
| 6007 |
| 6008 CallRuntimeFromDeferred( |
| 6009 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); |
| 6061 __ StoreToSafepointRegisterSlot(result, eax); | 6010 __ StoreToSafepointRegisterSlot(result, eax); |
| 6062 } | 6011 } |
| 6063 | 6012 |
| 6064 | 6013 |
| 6065 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 6014 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
| 6066 ASSERT(ToRegister(instr->value()).is(eax)); | 6015 ASSERT(ToRegister(instr->value()).is(eax)); |
| 6067 __ push(eax); | 6016 __ push(eax); |
| 6068 CallRuntime(Runtime::kToFastProperties, 1, instr); | 6017 CallRuntime(Runtime::kToFastProperties, 1, instr); |
| 6069 } | 6018 } |
| 6070 | 6019 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6144 void LCodeGen::DoTypeof(LTypeof* instr) { | 6093 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 6145 ASSERT(ToRegister(instr->context()).is(esi)); | 6094 ASSERT(ToRegister(instr->context()).is(esi)); |
| 6146 LOperand* input = instr->value(); | 6095 LOperand* input = instr->value(); |
| 6147 EmitPushTaggedOperand(input); | 6096 EmitPushTaggedOperand(input); |
| 6148 CallRuntime(Runtime::kTypeof, 1, instr); | 6097 CallRuntime(Runtime::kTypeof, 1, instr); |
| 6149 } | 6098 } |
| 6150 | 6099 |
| 6151 | 6100 |
| 6152 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 6101 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 6153 Register input = ToRegister(instr->value()); | 6102 Register input = ToRegister(instr->value()); |
| 6154 | 6103 Condition final_branch_condition = EmitTypeofIs(instr, input); |
| 6155 Condition final_branch_condition = | |
| 6156 EmitTypeofIs(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), | |
| 6157 input, instr->type_literal()); | |
| 6158 if (final_branch_condition != no_condition) { | 6104 if (final_branch_condition != no_condition) { |
| 6159 EmitBranch(instr, final_branch_condition); | 6105 EmitBranch(instr, final_branch_condition); |
| 6160 } | 6106 } |
| 6161 } | 6107 } |
| 6162 | 6108 |
| 6163 | 6109 |
| 6164 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 6110 Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) { |
| 6165 Label* false_label, | 6111 Label* true_label = instr->TrueLabel(chunk_); |
| 6166 Register input, | 6112 Label* false_label = instr->FalseLabel(chunk_); |
| 6167 Handle<String> type_name) { | 6113 Handle<String> type_name = instr->type_literal(); |
| 6114 int left_block = instr->TrueDestination(chunk_); |
| 6115 int right_block = instr->FalseDestination(chunk_); |
| 6116 int next_block = GetNextEmittedBlock(); |
| 6117 |
| 6118 Label::Distance true_distance = left_block == next_block ? Label::kNear |
| 6119 : Label::kFar; |
| 6120 Label::Distance false_distance = right_block == next_block ? Label::kNear |
| 6121 : Label::kFar; |
| 6168 Condition final_branch_condition = no_condition; | 6122 Condition final_branch_condition = no_condition; |
| 6169 if (type_name->Equals(heap()->number_string())) { | 6123 if (type_name->Equals(heap()->number_string())) { |
| 6170 __ JumpIfSmi(input, true_label); | 6124 __ JumpIfSmi(input, true_label, true_distance); |
| 6171 __ cmp(FieldOperand(input, HeapObject::kMapOffset), | 6125 __ cmp(FieldOperand(input, HeapObject::kMapOffset), |
| 6172 factory()->heap_number_map()); | 6126 factory()->heap_number_map()); |
| 6173 final_branch_condition = equal; | 6127 final_branch_condition = equal; |
| 6174 | 6128 |
| 6175 } else if (type_name->Equals(heap()->string_string())) { | 6129 } else if (type_name->Equals(heap()->string_string())) { |
| 6176 __ JumpIfSmi(input, false_label); | 6130 __ JumpIfSmi(input, false_label, false_distance); |
| 6177 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); | 6131 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); |
| 6178 __ j(above_equal, false_label); | 6132 __ j(above_equal, false_label, false_distance); |
| 6179 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 6133 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| 6180 1 << Map::kIsUndetectable); | 6134 1 << Map::kIsUndetectable); |
| 6181 final_branch_condition = zero; | 6135 final_branch_condition = zero; |
| 6182 | 6136 |
| 6183 } else if (type_name->Equals(heap()->symbol_string())) { | 6137 } else if (type_name->Equals(heap()->symbol_string())) { |
| 6184 __ JumpIfSmi(input, false_label); | 6138 __ JumpIfSmi(input, false_label, false_distance); |
| 6185 __ CmpObjectType(input, SYMBOL_TYPE, input); | 6139 __ CmpObjectType(input, SYMBOL_TYPE, input); |
| 6186 final_branch_condition = equal; | 6140 final_branch_condition = equal; |
| 6187 | 6141 |
| 6188 } else if (type_name->Equals(heap()->boolean_string())) { | 6142 } else if (type_name->Equals(heap()->boolean_string())) { |
| 6189 __ cmp(input, factory()->true_value()); | 6143 __ cmp(input, factory()->true_value()); |
| 6190 __ j(equal, true_label); | 6144 __ j(equal, true_label, true_distance); |
| 6191 __ cmp(input, factory()->false_value()); | 6145 __ cmp(input, factory()->false_value()); |
| 6192 final_branch_condition = equal; | 6146 final_branch_condition = equal; |
| 6193 | 6147 |
| 6194 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) { | 6148 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) { |
| 6195 __ cmp(input, factory()->null_value()); | 6149 __ cmp(input, factory()->null_value()); |
| 6196 final_branch_condition = equal; | 6150 final_branch_condition = equal; |
| 6197 | 6151 |
| 6198 } else if (type_name->Equals(heap()->undefined_string())) { | 6152 } else if (type_name->Equals(heap()->undefined_string())) { |
| 6199 __ cmp(input, factory()->undefined_value()); | 6153 __ cmp(input, factory()->undefined_value()); |
| 6200 __ j(equal, true_label); | 6154 __ j(equal, true_label, true_distance); |
| 6201 __ JumpIfSmi(input, false_label); | 6155 __ JumpIfSmi(input, false_label, false_distance); |
| 6202 // Check for undetectable objects => true. | 6156 // Check for undetectable objects => true. |
| 6203 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); | 6157 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); |
| 6204 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 6158 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| 6205 1 << Map::kIsUndetectable); | 6159 1 << Map::kIsUndetectable); |
| 6206 final_branch_condition = not_zero; | 6160 final_branch_condition = not_zero; |
| 6207 | 6161 |
| 6208 } else if (type_name->Equals(heap()->function_string())) { | 6162 } else if (type_name->Equals(heap()->function_string())) { |
| 6209 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); | 6163 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |
| 6210 __ JumpIfSmi(input, false_label); | 6164 __ JumpIfSmi(input, false_label, false_distance); |
| 6211 __ CmpObjectType(input, JS_FUNCTION_TYPE, input); | 6165 __ CmpObjectType(input, JS_FUNCTION_TYPE, input); |
| 6212 __ j(equal, true_label); | 6166 __ j(equal, true_label, true_distance); |
| 6213 __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); | 6167 __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); |
| 6214 final_branch_condition = equal; | 6168 final_branch_condition = equal; |
| 6215 | 6169 |
| 6216 } else if (type_name->Equals(heap()->object_string())) { | 6170 } else if (type_name->Equals(heap()->object_string())) { |
| 6217 __ JumpIfSmi(input, false_label); | 6171 __ JumpIfSmi(input, false_label, false_distance); |
| 6218 if (!FLAG_harmony_typeof) { | 6172 if (!FLAG_harmony_typeof) { |
| 6219 __ cmp(input, factory()->null_value()); | 6173 __ cmp(input, factory()->null_value()); |
| 6220 __ j(equal, true_label); | 6174 __ j(equal, true_label, true_distance); |
| 6221 } | 6175 } |
| 6222 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); | 6176 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); |
| 6223 __ j(below, false_label); | 6177 __ j(below, false_label, false_distance); |
| 6224 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 6178 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 6225 __ j(above, false_label); | 6179 __ j(above, false_label, false_distance); |
| 6226 // Check for undetectable objects => false. | 6180 // Check for undetectable objects => false. |
| 6227 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 6181 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| 6228 1 << Map::kIsUndetectable); | 6182 1 << Map::kIsUndetectable); |
| 6229 final_branch_condition = zero; | 6183 final_branch_condition = zero; |
| 6230 | 6184 |
| 6231 } else { | 6185 } else { |
| 6232 __ jmp(false_label); | 6186 __ jmp(false_label, false_distance); |
| 6233 } | 6187 } |
| 6234 return final_branch_condition; | 6188 return final_branch_condition; |
| 6235 } | 6189 } |
| 6236 | 6190 |
| 6237 | 6191 |
| 6238 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 6192 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 6239 Register temp = ToRegister(instr->temp()); | 6193 Register temp = ToRegister(instr->temp()); |
| 6240 | 6194 |
| 6241 EmitIsConstructCall(temp); | 6195 EmitIsConstructCall(temp); |
| 6242 EmitBranch(instr, equal); | 6196 EmitBranch(instr, equal); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6477 FixedArray::kHeaderSize - kPointerSize)); | 6431 FixedArray::kHeaderSize - kPointerSize)); |
| 6478 __ bind(&done); | 6432 __ bind(&done); |
| 6479 } | 6433 } |
| 6480 | 6434 |
| 6481 | 6435 |
| 6482 #undef __ | 6436 #undef __ |
| 6483 | 6437 |
| 6484 } } // namespace v8::internal | 6438 } } // namespace v8::internal |
| 6485 | 6439 |
| 6486 #endif // V8_TARGET_ARCH_IA32 | 6440 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |