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 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 | 276 |
277 | 277 |
278 void MacroAssembler::DoubleToI(Register result_reg, | 278 void MacroAssembler::DoubleToI(Register result_reg, |
279 XMMRegister input_reg, | 279 XMMRegister input_reg, |
280 XMMRegister scratch, | 280 XMMRegister scratch, |
281 MinusZeroMode minus_zero_mode, | 281 MinusZeroMode minus_zero_mode, |
282 Label* conversion_failed, | 282 Label* conversion_failed, |
283 Label::Distance dst) { | 283 Label::Distance dst) { |
284 ASSERT(!input_reg.is(scratch)); | 284 ASSERT(!input_reg.is(scratch)); |
285 cvttsd2si(result_reg, Operand(input_reg)); | 285 cvttsd2si(result_reg, Operand(input_reg)); |
286 Cvtsi2sd(scratch, Operand(result_reg)); | 286 cvtsi2sd(scratch, Operand(result_reg)); |
287 ucomisd(scratch, input_reg); | 287 ucomisd(scratch, input_reg); |
288 j(not_equal, conversion_failed, dst); | 288 j(not_equal, conversion_failed, dst); |
289 j(parity_even, conversion_failed, dst); // NaN. | 289 j(parity_even, conversion_failed, dst); // NaN. |
290 if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { | 290 if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { |
291 Label done; | 291 Label done; |
292 // The integer converted back is equal to the original. We | 292 // The integer converted back is equal to the original. We |
293 // only have to test if we got -0 as an input. | 293 // only have to test if we got -0 as an input. |
294 test(result_reg, Operand(result_reg)); | 294 test(result_reg, Operand(result_reg)); |
295 j(not_zero, &done, Label::kNear); | 295 j(not_zero, &done, Label::kNear); |
296 movmskpd(result_reg, input_reg); | 296 movmskpd(result_reg, input_reg); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 385 cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
386 isolate()->factory()->heap_number_map()); | 386 isolate()->factory()->heap_number_map()); |
387 j(not_equal, lost_precision, Label::kNear); | 387 j(not_equal, lost_precision, Label::kNear); |
388 | 388 |
389 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 389 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
390 ASSERT(!temp.is(no_xmm_reg)); | 390 ASSERT(!temp.is(no_xmm_reg)); |
391 CpuFeatureScope scope(this, SSE2); | 391 CpuFeatureScope scope(this, SSE2); |
392 | 392 |
393 movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 393 movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
394 cvttsd2si(result_reg, Operand(xmm0)); | 394 cvttsd2si(result_reg, Operand(xmm0)); |
395 Cvtsi2sd(temp, Operand(result_reg)); | 395 cvtsi2sd(temp, Operand(result_reg)); |
396 ucomisd(xmm0, temp); | 396 ucomisd(xmm0, temp); |
397 RecordComment("Deferred TaggedToI: lost precision"); | 397 RecordComment("Deferred TaggedToI: lost precision"); |
398 j(not_equal, lost_precision, Label::kNear); | 398 j(not_equal, lost_precision, Label::kNear); |
399 RecordComment("Deferred TaggedToI: NaN"); | 399 RecordComment("Deferred TaggedToI: NaN"); |
400 j(parity_even, lost_precision, Label::kNear); | 400 j(parity_even, lost_precision, Label::kNear); |
401 if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { | 401 if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { |
402 test(result_reg, Operand(result_reg)); | 402 test(result_reg, Operand(result_reg)); |
403 j(not_zero, &done, Label::kNear); | 403 j(not_zero, &done, Label::kNear); |
404 movmskpd(result_reg, xmm0); | 404 movmskpd(result_reg, xmm0); |
405 and_(result_reg, 1); | 405 and_(result_reg, 1); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1; | 450 static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1; |
451 | 451 |
452 | 452 |
453 void MacroAssembler::LoadUint32(XMMRegister dst, | 453 void MacroAssembler::LoadUint32(XMMRegister dst, |
454 Register src, | 454 Register src, |
455 XMMRegister scratch) { | 455 XMMRegister scratch) { |
456 Label done; | 456 Label done; |
457 cmp(src, Immediate(0)); | 457 cmp(src, Immediate(0)); |
458 movdbl(scratch, | 458 movdbl(scratch, |
459 Operand(reinterpret_cast<int32_t>(&kUint32Bias), RelocInfo::NONE32)); | 459 Operand(reinterpret_cast<int32_t>(&kUint32Bias), RelocInfo::NONE32)); |
460 Cvtsi2sd(dst, src); | 460 cvtsi2sd(dst, src); |
461 j(not_sign, &done, Label::kNear); | 461 j(not_sign, &done, Label::kNear); |
462 addsd(dst, scratch); | 462 addsd(dst, scratch); |
463 bind(&done); | 463 bind(&done); |
464 } | 464 } |
465 | 465 |
466 | 466 |
467 void MacroAssembler::RecordWriteArray(Register object, | 467 void MacroAssembler::RecordWriteArray(Register object, |
468 Register value, | 468 Register value, |
469 Register index, | 469 Register index, |
470 SaveFPRegsMode save_fp, | 470 SaveFPRegsMode save_fp, |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 #ifdef ENABLE_DEBUGGER_SUPPORT | 669 #ifdef ENABLE_DEBUGGER_SUPPORT |
670 void MacroAssembler::DebugBreak() { | 670 void MacroAssembler::DebugBreak() { |
671 Set(eax, Immediate(0)); | 671 Set(eax, Immediate(0)); |
672 mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak, isolate()))); | 672 mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak, isolate()))); |
673 CEntryStub ces(1); | 673 CEntryStub ces(1); |
674 call(ces.GetCode(isolate()), RelocInfo::DEBUG_BREAK); | 674 call(ces.GetCode(isolate()), RelocInfo::DEBUG_BREAK); |
675 } | 675 } |
676 #endif | 676 #endif |
677 | 677 |
678 | 678 |
679 void MacroAssembler::Cvtsi2sd(XMMRegister dst, const Operand& src) { | |
680 xorps(dst, dst); | |
681 cvtsi2sd(dst, src); | |
682 } | |
683 | |
684 | |
685 void MacroAssembler::Set(Register dst, const Immediate& x) { | 679 void MacroAssembler::Set(Register dst, const Immediate& x) { |
686 if (x.is_zero()) { | 680 if (x.is_zero()) { |
687 xor_(dst, dst); // Shorter than mov. | 681 xor_(dst, dst); // Shorter than mov. |
688 } else { | 682 } else { |
689 mov(dst, x); | 683 mov(dst, x); |
690 } | 684 } |
691 } | 685 } |
692 | 686 |
693 | 687 |
694 void MacroAssembler::Set(const Operand& dst, const Immediate& x) { | 688 void MacroAssembler::Set(const Operand& dst, const Immediate& x) { |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 } | 827 } |
834 jmp(&have_double_value, Label::kNear); | 828 jmp(&have_double_value, Label::kNear); |
835 | 829 |
836 bind(&smi_value); | 830 bind(&smi_value); |
837 // Value is a smi. Convert to a double and store. | 831 // Value is a smi. Convert to a double and store. |
838 // Preserve original value. | 832 // Preserve original value. |
839 mov(scratch1, maybe_number); | 833 mov(scratch1, maybe_number); |
840 SmiUntag(scratch1); | 834 SmiUntag(scratch1); |
841 if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) { | 835 if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) { |
842 CpuFeatureScope fscope(this, SSE2); | 836 CpuFeatureScope fscope(this, SSE2); |
843 Cvtsi2sd(scratch2, scratch1); | 837 cvtsi2sd(scratch2, scratch1); |
844 movdbl(FieldOperand(elements, key, times_4, | 838 movdbl(FieldOperand(elements, key, times_4, |
845 FixedDoubleArray::kHeaderSize - elements_offset), | 839 FixedDoubleArray::kHeaderSize - elements_offset), |
846 scratch2); | 840 scratch2); |
847 } else { | 841 } else { |
848 push(scratch1); | 842 push(scratch1); |
849 fild_s(Operand(esp, 0)); | 843 fild_s(Operand(esp, 0)); |
850 pop(scratch1); | 844 pop(scratch1); |
851 fstp_d(FieldOperand(elements, key, times_4, | 845 fstp_d(FieldOperand(elements, key, times_4, |
852 FixedDoubleArray::kHeaderSize - elements_offset)); | 846 FixedDoubleArray::kHeaderSize - elements_offset)); |
853 } | 847 } |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 // Get the return address from the stack and restore the frame pointer. | 1102 // Get the return address from the stack and restore the frame pointer. |
1109 mov(ecx, Operand(ebp, 1 * kPointerSize)); | 1103 mov(ecx, Operand(ebp, 1 * kPointerSize)); |
1110 mov(ebp, Operand(ebp, 0 * kPointerSize)); | 1104 mov(ebp, Operand(ebp, 0 * kPointerSize)); |
1111 | 1105 |
1112 // Pop the arguments and the receiver from the caller stack. | 1106 // Pop the arguments and the receiver from the caller stack. |
1113 lea(esp, Operand(esi, 1 * kPointerSize)); | 1107 lea(esp, Operand(esi, 1 * kPointerSize)); |
1114 | 1108 |
1115 // Push the return address to get ready to return. | 1109 // Push the return address to get ready to return. |
1116 push(ecx); | 1110 push(ecx); |
1117 | 1111 |
1118 LeaveExitFrameEpilogue(true); | 1112 LeaveExitFrameEpilogue(); |
1119 } | 1113 } |
1120 | 1114 |
1121 | 1115 |
1122 void MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) { | 1116 void MacroAssembler::LeaveExitFrameEpilogue() { |
1123 // Restore current context from top and clear it in debug mode. | 1117 // Restore current context from top and clear it in debug mode. |
1124 ExternalReference context_address(Isolate::kContextAddress, isolate()); | 1118 ExternalReference context_address(Isolate::kContextAddress, isolate()); |
1125 if (restore_context) { | 1119 mov(esi, Operand::StaticVariable(context_address)); |
1126 mov(esi, Operand::StaticVariable(context_address)); | |
1127 } | |
1128 #ifdef DEBUG | 1120 #ifdef DEBUG |
1129 mov(Operand::StaticVariable(context_address), Immediate(0)); | 1121 mov(Operand::StaticVariable(context_address), Immediate(0)); |
1130 #endif | 1122 #endif |
1131 | 1123 |
1132 // Clear the top frame. | 1124 // Clear the top frame. |
1133 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, | 1125 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, |
1134 isolate()); | 1126 isolate()); |
1135 mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0)); | 1127 mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0)); |
1136 } | 1128 } |
1137 | 1129 |
1138 | 1130 |
1139 void MacroAssembler::LeaveApiExitFrame(bool restore_context) { | 1131 void MacroAssembler::LeaveApiExitFrame() { |
1140 mov(esp, ebp); | 1132 mov(esp, ebp); |
1141 pop(ebp); | 1133 pop(ebp); |
1142 | 1134 |
1143 LeaveExitFrameEpilogue(restore_context); | 1135 LeaveExitFrameEpilogue(); |
1144 } | 1136 } |
1145 | 1137 |
1146 | 1138 |
1147 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, | 1139 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, |
1148 int handler_index) { | 1140 int handler_index) { |
1149 // Adjust this code if not the case. | 1141 // Adjust this code if not the case. |
1150 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 1142 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
1151 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 1143 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
1152 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); | 1144 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
1153 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); | 1145 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2222 | 2214 |
2223 | 2215 |
2224 void MacroAssembler::PrepareCallApiFunction(int argc) { | 2216 void MacroAssembler::PrepareCallApiFunction(int argc) { |
2225 EnterApiExitFrame(argc); | 2217 EnterApiExitFrame(argc); |
2226 if (emit_debug_code()) { | 2218 if (emit_debug_code()) { |
2227 mov(esi, Immediate(BitCast<int32_t>(kZapValue))); | 2219 mov(esi, Immediate(BitCast<int32_t>(kZapValue))); |
2228 } | 2220 } |
2229 } | 2221 } |
2230 | 2222 |
2231 | 2223 |
2232 void MacroAssembler::CallApiFunctionAndReturn( | 2224 void MacroAssembler::CallApiFunctionAndReturn(Address function_address, |
2233 Address function_address, | 2225 Address thunk_address, |
2234 Address thunk_address, | 2226 Operand thunk_last_arg, |
2235 Operand thunk_last_arg, | 2227 int stack_space, |
2236 int stack_space, | 2228 int return_value_offset) { |
2237 Operand return_value_operand, | |
2238 Operand* context_restore_operand) { | |
2239 ExternalReference next_address = | 2229 ExternalReference next_address = |
2240 ExternalReference::handle_scope_next_address(isolate()); | 2230 ExternalReference::handle_scope_next_address(isolate()); |
2241 ExternalReference limit_address = | 2231 ExternalReference limit_address = |
2242 ExternalReference::handle_scope_limit_address(isolate()); | 2232 ExternalReference::handle_scope_limit_address(isolate()); |
2243 ExternalReference level_address = | 2233 ExternalReference level_address = |
2244 ExternalReference::handle_scope_level_address(isolate()); | 2234 ExternalReference::handle_scope_level_address(isolate()); |
2245 | 2235 |
2246 // Allocate HandleScope in callee-save registers. | 2236 // Allocate HandleScope in callee-save registers. |
2247 mov(ebx, Operand::StaticVariable(next_address)); | 2237 mov(ebx, Operand::StaticVariable(next_address)); |
2248 mov(edi, Operand::StaticVariable(limit_address)); | 2238 mov(edi, Operand::StaticVariable(limit_address)); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2284 PushSafepointRegisters(); | 2274 PushSafepointRegisters(); |
2285 PrepareCallCFunction(1, eax); | 2275 PrepareCallCFunction(1, eax); |
2286 mov(Operand(esp, 0), | 2276 mov(Operand(esp, 0), |
2287 Immediate(ExternalReference::isolate_address(isolate()))); | 2277 Immediate(ExternalReference::isolate_address(isolate()))); |
2288 CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1); | 2278 CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1); |
2289 PopSafepointRegisters(); | 2279 PopSafepointRegisters(); |
2290 } | 2280 } |
2291 | 2281 |
2292 Label prologue; | 2282 Label prologue; |
2293 // Load the value from ReturnValue | 2283 // Load the value from ReturnValue |
2294 mov(eax, return_value_operand); | 2284 mov(eax, Operand(ebp, return_value_offset * kPointerSize)); |
2295 | 2285 |
2296 Label promote_scheduled_exception; | 2286 Label promote_scheduled_exception; |
2297 Label exception_handled; | |
2298 Label delete_allocated_handles; | 2287 Label delete_allocated_handles; |
2299 Label leave_exit_frame; | 2288 Label leave_exit_frame; |
2300 | 2289 |
2301 bind(&prologue); | 2290 bind(&prologue); |
2302 // No more valid handles (the result handle was the last one). Restore | 2291 // No more valid handles (the result handle was the last one). Restore |
2303 // previous handle scope. | 2292 // previous handle scope. |
2304 mov(Operand::StaticVariable(next_address), ebx); | 2293 mov(Operand::StaticVariable(next_address), ebx); |
2305 sub(Operand::StaticVariable(level_address), Immediate(1)); | 2294 sub(Operand::StaticVariable(level_address), Immediate(1)); |
2306 Assert(above_equal, kInvalidHandleScopeLevel); | 2295 Assert(above_equal, kInvalidHandleScopeLevel); |
2307 cmp(edi, Operand::StaticVariable(limit_address)); | 2296 cmp(edi, Operand::StaticVariable(limit_address)); |
2308 j(not_equal, &delete_allocated_handles); | 2297 j(not_equal, &delete_allocated_handles); |
2309 bind(&leave_exit_frame); | 2298 bind(&leave_exit_frame); |
2310 | 2299 |
2311 // Check if the function scheduled an exception. | 2300 // Check if the function scheduled an exception. |
2312 ExternalReference scheduled_exception_address = | 2301 ExternalReference scheduled_exception_address = |
2313 ExternalReference::scheduled_exception_address(isolate()); | 2302 ExternalReference::scheduled_exception_address(isolate()); |
2314 cmp(Operand::StaticVariable(scheduled_exception_address), | 2303 cmp(Operand::StaticVariable(scheduled_exception_address), |
2315 Immediate(isolate()->factory()->the_hole_value())); | 2304 Immediate(isolate()->factory()->the_hole_value())); |
2316 j(not_equal, &promote_scheduled_exception); | 2305 j(not_equal, &promote_scheduled_exception); |
2317 bind(&exception_handled); | |
2318 | 2306 |
2319 #if ENABLE_EXTRA_CHECKS | 2307 #if ENABLE_EXTRA_CHECKS |
2320 // Check if the function returned a valid JavaScript value. | 2308 // Check if the function returned a valid JavaScript value. |
2321 Label ok; | 2309 Label ok; |
2322 Register return_value = eax; | 2310 Register return_value = eax; |
2323 Register map = ecx; | 2311 Register map = ecx; |
2324 | 2312 |
2325 JumpIfSmi(return_value, &ok, Label::kNear); | 2313 JumpIfSmi(return_value, &ok, Label::kNear); |
2326 mov(map, FieldOperand(return_value, HeapObject::kMapOffset)); | 2314 mov(map, FieldOperand(return_value, HeapObject::kMapOffset)); |
2327 | 2315 |
(...skipping 16 matching lines...) Expand all Loading... |
2344 j(equal, &ok, Label::kNear); | 2332 j(equal, &ok, Label::kNear); |
2345 | 2333 |
2346 cmp(return_value, isolate()->factory()->null_value()); | 2334 cmp(return_value, isolate()->factory()->null_value()); |
2347 j(equal, &ok, Label::kNear); | 2335 j(equal, &ok, Label::kNear); |
2348 | 2336 |
2349 Abort(kAPICallReturnedInvalidObject); | 2337 Abort(kAPICallReturnedInvalidObject); |
2350 | 2338 |
2351 bind(&ok); | 2339 bind(&ok); |
2352 #endif | 2340 #endif |
2353 | 2341 |
2354 bool restore_context = context_restore_operand != NULL; | 2342 LeaveApiExitFrame(); |
2355 if (restore_context) { | |
2356 mov(esi, *context_restore_operand); | |
2357 } | |
2358 LeaveApiExitFrame(!restore_context); | |
2359 ret(stack_space * kPointerSize); | 2343 ret(stack_space * kPointerSize); |
2360 | 2344 |
2361 bind(&promote_scheduled_exception); | 2345 bind(&promote_scheduled_exception); |
2362 { | 2346 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
2363 FrameScope frame(this, StackFrame::INTERNAL); | |
2364 CallRuntime(Runtime::kPromoteScheduledException, 0); | |
2365 } | |
2366 jmp(&exception_handled); | |
2367 | 2347 |
2368 // HandleScope limit has changed. Delete allocated extensions. | 2348 // HandleScope limit has changed. Delete allocated extensions. |
2369 ExternalReference delete_extensions = | 2349 ExternalReference delete_extensions = |
2370 ExternalReference::delete_handle_scope_extensions(isolate()); | 2350 ExternalReference::delete_handle_scope_extensions(isolate()); |
2371 bind(&delete_allocated_handles); | 2351 bind(&delete_allocated_handles); |
2372 mov(Operand::StaticVariable(limit_address), edi); | 2352 mov(Operand::StaticVariable(limit_address), edi); |
2373 mov(edi, eax); | 2353 mov(edi, eax); |
2374 mov(Operand(esp, 0), | 2354 mov(Operand(esp, 0), |
2375 Immediate(ExternalReference::isolate_address(isolate()))); | 2355 Immediate(ExternalReference::isolate_address(isolate()))); |
2376 mov(eax, Immediate(delete_extensions)); | 2356 mov(eax, Immediate(delete_extensions)); |
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3444 j(greater, &no_memento_available); | 3424 j(greater, &no_memento_available); |
3445 cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), | 3425 cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), |
3446 Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map()))); | 3426 Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map()))); |
3447 bind(&no_memento_available); | 3427 bind(&no_memento_available); |
3448 } | 3428 } |
3449 | 3429 |
3450 | 3430 |
3451 } } // namespace v8::internal | 3431 } } // namespace v8::internal |
3452 | 3432 |
3453 #endif // V8_TARGET_ARCH_IA32 | 3433 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |