| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 | 542 |
| 543 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 543 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 544 RelocInfo::Mode mode, | 544 RelocInfo::Mode mode, |
| 545 LInstruction* instr, | 545 LInstruction* instr, |
| 546 SafepointMode safepoint_mode) { | 546 SafepointMode safepoint_mode) { |
| 547 ASSERT(instr != NULL); | 547 ASSERT(instr != NULL); |
| 548 LPointerMap* pointers = instr->pointer_map(); | 548 LPointerMap* pointers = instr->pointer_map(); |
| 549 RecordPosition(pointers->position()); | 549 RecordPosition(pointers->position()); |
| 550 __ Call(code, mode); | 550 __ Call(code, mode); |
| 551 RegisterLazyDeoptimization(instr, safepoint_mode); | 551 RegisterLazyDeoptimization(instr, safepoint_mode); |
| 552 |
| 553 // Signal that we don't inline smi code before these stubs in the |
| 554 // optimizing code generator. |
| 555 if (code->kind() == Code::BINARY_OP_IC || |
| 556 code->kind() == Code::COMPARE_IC) { |
| 557 __ nop(); |
| 558 } |
| 552 } | 559 } |
| 553 | 560 |
| 554 | 561 |
| 555 void LCodeGen::CallRuntime(const Runtime::Function* function, | 562 void LCodeGen::CallRuntime(const Runtime::Function* function, |
| 556 int num_arguments, | 563 int num_arguments, |
| 557 LInstruction* instr) { | 564 LInstruction* instr) { |
| 558 ASSERT(instr != NULL); | 565 ASSERT(instr != NULL); |
| 559 LPointerMap* pointers = instr->pointer_map(); | 566 LPointerMap* pointers = instr->pointer_map(); |
| 560 ASSERT(pointers != NULL); | 567 ASSERT(pointers != NULL); |
| 561 RecordPosition(pointers->position()); | 568 RecordPosition(pointers->position()); |
| (...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1497 } | 1504 } |
| 1498 | 1505 |
| 1499 | 1506 |
| 1500 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1507 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1501 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); | 1508 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); |
| 1502 ASSERT(ToRegister(instr->InputAt(1)).is(r0)); | 1509 ASSERT(ToRegister(instr->InputAt(1)).is(r0)); |
| 1503 ASSERT(ToRegister(instr->result()).is(r0)); | 1510 ASSERT(ToRegister(instr->result()).is(r0)); |
| 1504 | 1511 |
| 1505 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1512 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1506 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1513 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1514 __ nop(); // Signals no inlined code. |
| 1507 } | 1515 } |
| 1508 | 1516 |
| 1509 | 1517 |
| 1510 int LCodeGen::GetNextEmittedBlock(int block) { | 1518 int LCodeGen::GetNextEmittedBlock(int block) { |
| 1511 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { | 1519 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { |
| 1512 LLabel* label = chunk_->GetLabel(i); | 1520 LLabel* label = chunk_->GetLabel(i); |
| 1513 if (!label->HasReplacement()) return i; | 1521 if (!label->HasReplacement()) return i; |
| 1514 } | 1522 } |
| 1515 return -1; | 1523 return -1; |
| 1516 } | 1524 } |
| (...skipping 904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2421 | 2429 |
| 2422 // Check for the hole value. | 2430 // Check for the hole value. |
| 2423 if (instr->hydrogen()->RequiresHoleCheck()) { | 2431 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2424 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 2432 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 2425 __ cmp(result, scratch); | 2433 __ cmp(result, scratch); |
| 2426 DeoptimizeIf(eq, instr->environment()); | 2434 DeoptimizeIf(eq, instr->environment()); |
| 2427 } | 2435 } |
| 2428 } | 2436 } |
| 2429 | 2437 |
| 2430 | 2438 |
| 2439 void LCodeGen::DoLoadKeyedFastDoubleElement( |
| 2440 LLoadKeyedFastDoubleElement* instr) { |
| 2441 Register elements = ToRegister(instr->elements()); |
| 2442 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 2443 Register key = no_reg; |
| 2444 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 2445 Register scratch = scratch0(); |
| 2446 |
| 2447 int shift_size = |
| 2448 ElementsKindToShiftSize(JSObject::FAST_DOUBLE_ELEMENTS); |
| 2449 int constant_key = 0; |
| 2450 if (key_is_constant) { |
| 2451 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 2452 if (constant_key & 0xF0000000) { |
| 2453 Abort("array index constant value too big."); |
| 2454 } |
| 2455 } else { |
| 2456 key = ToRegister(instr->key()); |
| 2457 } |
| 2458 |
| 2459 Operand operand = key_is_constant |
| 2460 ? Operand(constant_key * (1 << shift_size) + |
| 2461 FixedDoubleArray::kHeaderSize - kHeapObjectTag) |
| 2462 : Operand(key, LSL, shift_size); |
| 2463 __ add(elements, elements, operand); |
| 2464 if (!key_is_constant) { |
| 2465 __ add(elements, elements, |
| 2466 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 2467 } |
| 2468 |
| 2469 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2470 // TODO(danno): If no hole check is required, there is no need to allocate |
| 2471 // elements into a temporary register, instead scratch can be used. |
| 2472 __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); |
| 2473 __ cmp(scratch, Operand(kHoleNanUpper32)); |
| 2474 DeoptimizeIf(eq, instr->environment()); |
| 2475 } |
| 2476 |
| 2477 __ vldr(result, elements, 0); |
| 2478 } |
| 2479 |
| 2480 |
| 2431 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | 2481 void LCodeGen::DoLoadKeyedSpecializedArrayElement( |
| 2432 LLoadKeyedSpecializedArrayElement* instr) { | 2482 LLoadKeyedSpecializedArrayElement* instr) { |
| 2433 Register external_pointer = ToRegister(instr->external_pointer()); | 2483 Register external_pointer = ToRegister(instr->external_pointer()); |
| 2434 Register key = no_reg; | 2484 Register key = no_reg; |
| 2435 JSObject::ElementsKind elements_kind = instr->elements_kind(); | 2485 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 2436 bool key_is_constant = instr->key()->IsConstantOperand(); | 2486 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 2437 int constant_key = 0; | 2487 int constant_key = 0; |
| 2438 if (key_is_constant) { | 2488 if (key_is_constant) { |
| 2439 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 2489 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 2440 if (constant_key & 0xF0000000) { | 2490 if (constant_key & 0xF0000000) { |
| 2441 Abort("array index constant value too big."); | 2491 Abort("array index constant value too big."); |
| 2442 } | 2492 } |
| 2443 } else { | 2493 } else { |
| 2444 key = ToRegister(instr->key()); | 2494 key = ToRegister(instr->key()); |
| 2445 } | 2495 } |
| 2446 int shift_size = ElementsKindToShiftSize(elements_kind); | 2496 int shift_size = ElementsKindToShiftSize(elements_kind); |
| 2447 | 2497 |
| 2448 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS || | 2498 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS || |
| 2449 elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { | 2499 elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 2450 CpuFeatures::Scope scope(VFP3); | 2500 CpuFeatures::Scope scope(VFP3); |
| 2451 DwVfpRegister result(ToDoubleRegister(instr->result())); | 2501 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 2452 Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size)) | 2502 Operand operand = key_is_constant |
| 2453 : Operand(key, LSL, shift_size)); | 2503 ? Operand(constant_key * (1 << shift_size)) |
| 2504 : Operand(key, LSL, shift_size); |
| 2454 __ add(scratch0(), external_pointer, operand); | 2505 __ add(scratch0(), external_pointer, operand); |
| 2455 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { | 2506 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 2456 __ vldr(result.low(), scratch0(), 0); | 2507 __ vldr(result.low(), scratch0(), 0); |
| 2457 __ vcvt_f64_f32(result, result.low()); | 2508 __ vcvt_f64_f32(result, result.low()); |
| 2458 } else { // i.e. elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS | 2509 } else { // i.e. elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS |
| 2459 __ vldr(result, scratch0(), 0); | 2510 __ vldr(result, scratch0(), 0); |
| 2460 } | 2511 } |
| 2461 } else { | 2512 } else { |
| 2462 Register result(ToRegister(instr->result())); | 2513 Register result = ToRegister(instr->result()); |
| 2463 MemOperand mem_operand(key_is_constant | 2514 MemOperand mem_operand(key_is_constant |
| 2464 ? MemOperand(external_pointer, constant_key * (1 << shift_size)) | 2515 ? MemOperand(external_pointer, constant_key * (1 << shift_size)) |
| 2465 : MemOperand(external_pointer, key, LSL, shift_size)); | 2516 : MemOperand(external_pointer, key, LSL, shift_size)); |
| 2466 switch (elements_kind) { | 2517 switch (elements_kind) { |
| 2467 case JSObject::EXTERNAL_BYTE_ELEMENTS: | 2518 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 2468 __ ldrsb(result, mem_operand); | 2519 __ ldrsb(result, mem_operand); |
| 2469 break; | 2520 break; |
| 2470 case JSObject::EXTERNAL_PIXEL_ELEMENTS: | 2521 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 2471 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 2522 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 2472 __ ldrb(result, mem_operand); | 2523 __ ldrb(result, mem_operand); |
| (...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3233 } | 3284 } |
| 3234 | 3285 |
| 3235 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3286 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3236 // Compute address of modified element and store it into key register. | 3287 // Compute address of modified element and store it into key register. |
| 3237 __ add(key, scratch, Operand(FixedArray::kHeaderSize)); | 3288 __ add(key, scratch, Operand(FixedArray::kHeaderSize)); |
| 3238 __ RecordWrite(elements, key, value, kLRHasBeenSaved, kSaveFPRegs); | 3289 __ RecordWrite(elements, key, value, kLRHasBeenSaved, kSaveFPRegs); |
| 3239 } | 3290 } |
| 3240 } | 3291 } |
| 3241 | 3292 |
| 3242 | 3293 |
| 3294 void LCodeGen::DoStoreKeyedFastDoubleElement( |
| 3295 LStoreKeyedFastDoubleElement* instr) { |
| 3296 DwVfpRegister value = ToDoubleRegister(instr->value()); |
| 3297 Register elements = ToRegister(instr->elements()); |
| 3298 Register key = no_reg; |
| 3299 Register scratch = scratch0(); |
| 3300 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 3301 int constant_key = 0; |
| 3302 Label not_nan; |
| 3303 |
| 3304 // Calculate the effective address of the slot in the array to store the |
| 3305 // double value. |
| 3306 if (key_is_constant) { |
| 3307 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 3308 if (constant_key & 0xF0000000) { |
| 3309 Abort("array index constant value too big."); |
| 3310 } |
| 3311 } else { |
| 3312 key = ToRegister(instr->key()); |
| 3313 } |
| 3314 int shift_size = ElementsKindToShiftSize(JSObject::FAST_DOUBLE_ELEMENTS); |
| 3315 Operand operand = key_is_constant |
| 3316 ? Operand(constant_key * (1 << shift_size) + |
| 3317 FixedDoubleArray::kHeaderSize - kHeapObjectTag) |
| 3318 : Operand(key, LSL, shift_size); |
| 3319 __ add(scratch, elements, operand); |
| 3320 if (!key_is_constant) { |
| 3321 __ add(scratch, scratch, |
| 3322 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 3323 } |
| 3324 |
| 3325 // Check for NaN. All NaNs must be canonicalized. |
| 3326 __ VFPCompareAndSetFlags(value, value); |
| 3327 |
| 3328 // Only load canonical NaN if the comparison above set the overflow. |
| 3329 __ Vmov(value, FixedDoubleArray::canonical_not_the_hole_nan_as_double(), vs); |
| 3330 |
| 3331 __ bind(¬_nan); |
| 3332 __ vstr(value, scratch, 0); |
| 3333 } |
| 3334 |
| 3335 |
| 3243 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | 3336 void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
| 3244 LStoreKeyedSpecializedArrayElement* instr) { | 3337 LStoreKeyedSpecializedArrayElement* instr) { |
| 3245 | 3338 |
| 3246 Register external_pointer = ToRegister(instr->external_pointer()); | 3339 Register external_pointer = ToRegister(instr->external_pointer()); |
| 3247 Register key = no_reg; | 3340 Register key = no_reg; |
| 3248 JSObject::ElementsKind elements_kind = instr->elements_kind(); | 3341 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 3249 bool key_is_constant = instr->key()->IsConstantOperand(); | 3342 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 3250 int constant_key = 0; | 3343 int constant_key = 0; |
| 3251 if (key_is_constant) { | 3344 if (key_is_constant) { |
| 3252 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 3345 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| (...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3975 | 4068 |
| 3976 // Check for heap number | 4069 // Check for heap number |
| 3977 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4070 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 3978 __ cmp(scratch, Operand(factory()->heap_number_map())); | 4071 __ cmp(scratch, Operand(factory()->heap_number_map())); |
| 3979 __ b(eq, &heap_number); | 4072 __ b(eq, &heap_number); |
| 3980 | 4073 |
| 3981 // Check for undefined. Undefined is converted to zero for clamping | 4074 // Check for undefined. Undefined is converted to zero for clamping |
| 3982 // conversions. | 4075 // conversions. |
| 3983 __ cmp(input_reg, Operand(factory()->undefined_value())); | 4076 __ cmp(input_reg, Operand(factory()->undefined_value())); |
| 3984 DeoptimizeIf(ne, instr->environment()); | 4077 DeoptimizeIf(ne, instr->environment()); |
| 3985 __ movt(input_reg, 0); | 4078 __ mov(result_reg, Operand(0)); |
| 3986 __ jmp(&done); | 4079 __ jmp(&done); |
| 3987 | 4080 |
| 3988 // Heap number | 4081 // Heap number |
| 3989 __ bind(&heap_number); | 4082 __ bind(&heap_number); |
| 3990 __ vldr(double_scratch0(), FieldMemOperand(input_reg, | 4083 __ vldr(double_scratch0(), FieldMemOperand(input_reg, |
| 3991 HeapNumber::kValueOffset)); | 4084 HeapNumber::kValueOffset)); |
| 3992 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); | 4085 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); |
| 3993 __ jmp(&done); | 4086 __ jmp(&done); |
| 3994 | 4087 |
| 3995 // smi | 4088 // smi |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4397 ASSERT(osr_pc_offset_ == -1); | 4490 ASSERT(osr_pc_offset_ == -1); |
| 4398 osr_pc_offset_ = masm()->pc_offset(); | 4491 osr_pc_offset_ = masm()->pc_offset(); |
| 4399 } | 4492 } |
| 4400 | 4493 |
| 4401 | 4494 |
| 4402 | 4495 |
| 4403 | 4496 |
| 4404 #undef __ | 4497 #undef __ |
| 4405 | 4498 |
| 4406 } } // namespace v8::internal | 4499 } } // namespace v8::internal |
| OLD | NEW |