OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 } | 251 } |
252 | 252 |
253 Bind(&return_minus_x); | 253 Bind(&return_minus_x); |
254 var_x.Bind(Float64Neg(var_x.value())); | 254 var_x.Bind(Float64Neg(var_x.value())); |
255 Goto(&return_x); | 255 Goto(&return_x); |
256 | 256 |
257 Bind(&return_x); | 257 Bind(&return_x); |
258 return var_x.value(); | 258 return var_x.value(); |
259 } | 259 } |
260 | 260 |
| 261 Node* CodeStubAssembler::Float64RoundToEven(Node* x) { |
| 262 if (IsFloat64RoundTiesEvenSupported()) { |
| 263 return Float64RoundTiesEven(x); |
| 264 } |
| 265 // See ES#sec-touint8clamp for details. |
| 266 Node* f = Float64Floor(x); |
| 267 Node* f_and_half = Float64Add(f, Float64Constant(0.5)); |
| 268 |
| 269 Variable var_result(this, MachineRepresentation::kFloat64); |
| 270 Label return_f(this), return_f_plus_one(this), done(this); |
| 271 |
| 272 GotoIf(Float64LessThan(f_and_half, x), &return_f_plus_one); |
| 273 GotoIf(Float64LessThan(x, f_and_half), &return_f); |
| 274 { |
| 275 Node* f_mod_2 = Float64Mod(f, Float64Constant(2.0)); |
| 276 Branch(Float64Equal(f_mod_2, Float64Constant(0.0)), &return_f, |
| 277 &return_f_plus_one); |
| 278 } |
| 279 |
| 280 Bind(&return_f); |
| 281 var_result.Bind(f); |
| 282 Goto(&done); |
| 283 |
| 284 Bind(&return_f_plus_one); |
| 285 var_result.Bind(Float64Add(f, Float64Constant(1.0))); |
| 286 Goto(&done); |
| 287 |
| 288 Bind(&done); |
| 289 return var_result.value(); |
| 290 } |
| 291 |
261 Node* CodeStubAssembler::Float64Trunc(Node* x) { | 292 Node* CodeStubAssembler::Float64Trunc(Node* x) { |
262 if (IsFloat64RoundTruncateSupported()) { | 293 if (IsFloat64RoundTruncateSupported()) { |
263 return Float64RoundTruncate(x); | 294 return Float64RoundTruncate(x); |
264 } | 295 } |
265 | 296 |
266 Node* one = Float64Constant(1.0); | 297 Node* one = Float64Constant(1.0); |
267 Node* zero = Float64Constant(0.0); | 298 Node* zero = Float64Constant(0.0); |
268 Node* two_52 = Float64Constant(4503599627370496.0E0); | 299 Node* two_52 = Float64Constant(4503599627370496.0E0); |
269 Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); | 300 Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); |
270 | 301 |
(...skipping 5123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5394 Node* native_context = LoadNativeContext(context); | 5425 Node* native_context = LoadNativeContext(context); |
5395 Node* script_context_table = | 5426 Node* script_context_table = |
5396 LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); | 5427 LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); |
5397 | 5428 |
5398 int offset = | 5429 int offset = |
5399 ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; | 5430 ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; |
5400 return Load(MachineType::AnyTagged(), script_context_table, | 5431 return Load(MachineType::AnyTagged(), script_context_table, |
5401 IntPtrConstant(offset)); | 5432 IntPtrConstant(offset)); |
5402 } | 5433 } |
5403 | 5434 |
5404 Node* CodeStubAssembler::ClampedToUint8(Node* int32_value) { | |
5405 Label done(this); | |
5406 Node* int32_zero = Int32Constant(0); | |
5407 Node* int32_255 = Int32Constant(255); | |
5408 Variable var_value(this, MachineRepresentation::kWord32); | |
5409 var_value.Bind(int32_value); | |
5410 GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done); | |
5411 var_value.Bind(int32_zero); | |
5412 GotoIf(Int32LessThan(int32_value, int32_zero), &done); | |
5413 var_value.Bind(int32_255); | |
5414 Goto(&done); | |
5415 Bind(&done); | |
5416 return var_value.value(); | |
5417 } | |
5418 | |
5419 namespace { | 5435 namespace { |
5420 | 5436 |
5421 // Converts typed array elements kind to a machine representations. | 5437 // Converts typed array elements kind to a machine representations. |
5422 MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) { | 5438 MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) { |
5423 switch (kind) { | 5439 switch (kind) { |
5424 case UINT8_CLAMPED_ELEMENTS: | 5440 case UINT8_CLAMPED_ELEMENTS: |
5425 case UINT8_ELEMENTS: | 5441 case UINT8_ELEMENTS: |
5426 case INT8_ELEMENTS: | 5442 case INT8_ELEMENTS: |
5427 return MachineRepresentation::kWord8; | 5443 return MachineRepresentation::kWord8; |
5428 case UINT16_ELEMENTS: | 5444 case UINT16_ELEMENTS: |
(...skipping 12 matching lines...) Expand all Loading... |
5441 } | 5457 } |
5442 } | 5458 } |
5443 | 5459 |
5444 } // namespace | 5460 } // namespace |
5445 | 5461 |
5446 void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, | 5462 void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, |
5447 Node* index, Node* value, | 5463 Node* index, Node* value, |
5448 ParameterMode mode) { | 5464 ParameterMode mode) { |
5449 if (IsFixedTypedArrayElementsKind(kind)) { | 5465 if (IsFixedTypedArrayElementsKind(kind)) { |
5450 if (kind == UINT8_CLAMPED_ELEMENTS) { | 5466 if (kind == UINT8_CLAMPED_ELEMENTS) { |
5451 value = ClampedToUint8(value); | 5467 CSA_ASSERT(this, |
| 5468 Word32Equal(value, Word32And(Int32Constant(0xff), value))); |
5452 } | 5469 } |
5453 Node* offset = ElementOffsetFromIndex(index, kind, mode, 0); | 5470 Node* offset = ElementOffsetFromIndex(index, kind, mode, 0); |
5454 MachineRepresentation rep = ElementsKindToMachineRepresentation(kind); | 5471 MachineRepresentation rep = ElementsKindToMachineRepresentation(kind); |
5455 StoreNoWriteBarrier(rep, elements, offset, value); | 5472 StoreNoWriteBarrier(rep, elements, offset, value); |
5456 return; | 5473 return; |
5457 } | 5474 } |
5458 | 5475 |
5459 WriteBarrierMode barrier_mode = | 5476 WriteBarrierMode barrier_mode = |
5460 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; | 5477 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; |
5461 if (IsFastDoubleElementsKind(kind)) { | 5478 if (IsFastDoubleElementsKind(kind)) { |
5462 // Make sure we do not store signalling NaNs into double arrays. | 5479 // Make sure we do not store signalling NaNs into double arrays. |
5463 value = Float64SilenceNaN(value); | 5480 value = Float64SilenceNaN(value); |
5464 StoreFixedDoubleArrayElement(elements, index, value, mode); | 5481 StoreFixedDoubleArrayElement(elements, index, value, mode); |
5465 } else { | 5482 } else { |
5466 StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode); | 5483 StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode); |
5467 } | 5484 } |
5468 } | 5485 } |
5469 | 5486 |
| 5487 Node* CodeStubAssembler::Int32ToUint8Clamped(Node* int32_value) { |
| 5488 Label done(this); |
| 5489 Node* int32_zero = Int32Constant(0); |
| 5490 Node* int32_255 = Int32Constant(255); |
| 5491 Variable var_value(this, MachineRepresentation::kWord32); |
| 5492 var_value.Bind(int32_value); |
| 5493 GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done); |
| 5494 var_value.Bind(int32_zero); |
| 5495 GotoIf(Int32LessThan(int32_value, int32_zero), &done); |
| 5496 var_value.Bind(int32_255); |
| 5497 Goto(&done); |
| 5498 Bind(&done); |
| 5499 return var_value.value(); |
| 5500 } |
| 5501 |
| 5502 Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) { |
| 5503 Label done(this); |
| 5504 Variable var_value(this, MachineRepresentation::kWord32); |
| 5505 var_value.Bind(Int32Constant(0)); |
| 5506 GotoIf(Float64LessThanOrEqual(float64_value, Float64Constant(0.0)), &done); |
| 5507 var_value.Bind(Int32Constant(255)); |
| 5508 GotoIf(Float64LessThanOrEqual(Float64Constant(255.0), float64_value), &done); |
| 5509 { |
| 5510 Node* rounded_value = Float64RoundToEven(float64_value); |
| 5511 var_value.Bind(TruncateFloat64ToWord32(rounded_value)); |
| 5512 Goto(&done); |
| 5513 } |
| 5514 Bind(&done); |
| 5515 return var_value.value(); |
| 5516 } |
| 5517 |
| 5518 Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( |
| 5519 Node* input, ElementsKind elements_kind, Label* bailout) { |
| 5520 DCHECK(IsFixedTypedArrayElementsKind(elements_kind)); |
| 5521 |
| 5522 MachineRepresentation rep; |
| 5523 switch (elements_kind) { |
| 5524 case UINT8_ELEMENTS: |
| 5525 case INT8_ELEMENTS: |
| 5526 case UINT16_ELEMENTS: |
| 5527 case INT16_ELEMENTS: |
| 5528 case UINT32_ELEMENTS: |
| 5529 case INT32_ELEMENTS: |
| 5530 case UINT8_CLAMPED_ELEMENTS: |
| 5531 rep = MachineRepresentation::kWord32; |
| 5532 break; |
| 5533 case FLOAT32_ELEMENTS: |
| 5534 rep = MachineRepresentation::kFloat32; |
| 5535 break; |
| 5536 case FLOAT64_ELEMENTS: |
| 5537 rep = MachineRepresentation::kFloat64; |
| 5538 break; |
| 5539 default: |
| 5540 UNREACHABLE(); |
| 5541 return nullptr; |
| 5542 } |
| 5543 |
| 5544 Variable var_result(this, rep); |
| 5545 Label done(this, &var_result), if_smi(this); |
| 5546 GotoIf(TaggedIsSmi(input), &if_smi); |
| 5547 // Try to convert a heap number to a Smi. |
| 5548 GotoUnless(IsHeapNumberMap(LoadMap(input)), bailout); |
| 5549 { |
| 5550 Node* value = LoadHeapNumberValue(input); |
| 5551 if (rep == MachineRepresentation::kWord32) { |
| 5552 if (elements_kind == UINT8_CLAMPED_ELEMENTS) { |
| 5553 value = Float64ToUint8Clamped(value); |
| 5554 } else { |
| 5555 value = TruncateFloat64ToWord32(value); |
| 5556 } |
| 5557 } else if (rep == MachineRepresentation::kFloat32) { |
| 5558 value = TruncateFloat64ToFloat32(value); |
| 5559 } else { |
| 5560 DCHECK_EQ(MachineRepresentation::kFloat64, rep); |
| 5561 } |
| 5562 var_result.Bind(value); |
| 5563 Goto(&done); |
| 5564 } |
| 5565 |
| 5566 Bind(&if_smi); |
| 5567 { |
| 5568 Node* value = SmiToWord32(input); |
| 5569 if (rep == MachineRepresentation::kFloat32) { |
| 5570 value = RoundInt32ToFloat32(value); |
| 5571 } else if (rep == MachineRepresentation::kFloat64) { |
| 5572 value = ChangeInt32ToFloat64(value); |
| 5573 } else { |
| 5574 DCHECK_EQ(MachineRepresentation::kWord32, rep); |
| 5575 if (elements_kind == UINT8_CLAMPED_ELEMENTS) { |
| 5576 value = Int32ToUint8Clamped(value); |
| 5577 } |
| 5578 } |
| 5579 var_result.Bind(value); |
| 5580 Goto(&done); |
| 5581 } |
| 5582 |
| 5583 Bind(&done); |
| 5584 return var_result.value(); |
| 5585 } |
| 5586 |
5470 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, | 5587 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, |
5471 bool is_jsarray, | 5588 bool is_jsarray, |
5472 ElementsKind elements_kind, | 5589 ElementsKind elements_kind, |
5473 KeyedAccessStoreMode store_mode, | 5590 KeyedAccessStoreMode store_mode, |
5474 Label* bailout) { | 5591 Label* bailout) { |
5475 Node* elements = LoadElements(object); | 5592 Node* elements = LoadElements(object); |
5476 if (IsFastSmiOrObjectElementsKind(elements_kind) && | 5593 if (IsFastSmiOrObjectElementsKind(elements_kind) && |
5477 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 5594 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
5478 // Bailout in case of COW elements. | 5595 // Bailout in case of COW elements. |
5479 GotoIf(WordNotEqual(LoadMap(elements), | 5596 GotoIf(WordNotEqual(LoadMap(elements), |
5480 LoadRoot(Heap::kFixedArrayMapRootIndex)), | 5597 LoadRoot(Heap::kFixedArrayMapRootIndex)), |
5481 bailout); | 5598 bailout); |
5482 } | 5599 } |
5483 // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode(). | 5600 // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode(). |
5484 ParameterMode parameter_mode = INTPTR_PARAMETERS; | 5601 ParameterMode parameter_mode = INTPTR_PARAMETERS; |
5485 key = TryToIntptr(key, bailout); | 5602 key = TryToIntptr(key, bailout); |
5486 | 5603 |
5487 if (IsFixedTypedArrayElementsKind(elements_kind)) { | 5604 if (IsFixedTypedArrayElementsKind(elements_kind)) { |
5488 Label done(this); | 5605 Label done(this); |
5489 // TODO(ishell): call ToNumber() on value and don't bailout but be careful | 5606 // TODO(ishell): call ToNumber() on value and don't bailout but be careful |
5490 // to call it only once if we decide to bailout because of bounds checks. | 5607 // to call it only once if we decide to bailout because of bounds checks. |
5491 | 5608 |
5492 if (IsFixedFloatElementsKind(elements_kind)) { | 5609 value = PrepareValueForWriteToTypedArray(value, elements_kind, bailout); |
5493 // TODO(ishell): move float32 truncation into PrepareValueForWrite. | |
5494 value = PrepareValueForWrite(value, Representation::Double(), bailout); | |
5495 if (elements_kind == FLOAT32_ELEMENTS) { | |
5496 value = TruncateFloat64ToFloat32(value); | |
5497 } | |
5498 } else { | |
5499 // TODO(ishell): It's fine for word8/16/32 to truncate the result. | |
5500 value = TryToIntptr(value, bailout); | |
5501 } | |
5502 | 5610 |
5503 // There must be no allocations between the buffer load and | 5611 // There must be no allocations between the buffer load and |
5504 // and the actual store to backing store, because GC may decide that | 5612 // and the actual store to backing store, because GC may decide that |
5505 // the buffer is not alive or move the elements. | 5613 // the buffer is not alive or move the elements. |
5506 // TODO(ishell): introduce DisallowHeapAllocationCode scope here. | 5614 // TODO(ishell): introduce DisallowHeapAllocationCode scope here. |
5507 | 5615 |
5508 // Check if buffer has been neutered. | 5616 // Check if buffer has been neutered. |
5509 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); | 5617 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); |
5510 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, | 5618 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, |
5511 MachineType::Uint32()); | 5619 MachineType::Uint32()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5545 Node* length = is_jsarray ? LoadObjectField(object, JSArray::kLengthOffset) | 5653 Node* length = is_jsarray ? LoadObjectField(object, JSArray::kLengthOffset) |
5546 : LoadFixedArrayBaseLength(elements); | 5654 : LoadFixedArrayBaseLength(elements); |
5547 length = UntagParameter(length, parameter_mode); | 5655 length = UntagParameter(length, parameter_mode); |
5548 | 5656 |
5549 // In case value is stored into a fast smi array, assure that the value is | 5657 // In case value is stored into a fast smi array, assure that the value is |
5550 // a smi before manipulating the backing store. Otherwise the backing store | 5658 // a smi before manipulating the backing store. Otherwise the backing store |
5551 // may be left in an invalid state. | 5659 // may be left in an invalid state. |
5552 if (IsFastSmiElementsKind(elements_kind)) { | 5660 if (IsFastSmiElementsKind(elements_kind)) { |
5553 GotoUnless(TaggedIsSmi(value), bailout); | 5661 GotoUnless(TaggedIsSmi(value), bailout); |
5554 } else if (IsFastDoubleElementsKind(elements_kind)) { | 5662 } else if (IsFastDoubleElementsKind(elements_kind)) { |
5555 value = PrepareValueForWrite(value, Representation::Double(), bailout); | 5663 value = TryTaggedToFloat64(value, bailout); |
5556 } | 5664 } |
5557 | 5665 |
5558 if (IsGrowStoreMode(store_mode)) { | 5666 if (IsGrowStoreMode(store_mode)) { |
5559 elements = CheckForCapacityGrow(object, elements, elements_kind, length, | 5667 elements = CheckForCapacityGrow(object, elements, elements_kind, length, |
5560 key, parameter_mode, is_jsarray, bailout); | 5668 key, parameter_mode, is_jsarray, bailout); |
5561 } else { | 5669 } else { |
5562 GotoUnless(UintPtrLessThan(key, length), bailout); | 5670 GotoUnless(UintPtrLessThan(key, length), bailout); |
5563 | 5671 |
5564 if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW) && | 5672 if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW) && |
5565 IsFastSmiOrObjectElementsKind(elements_kind)) { | 5673 IsFastSmiOrObjectElementsKind(elements_kind)) { |
(...skipping 2283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7849 | 7957 |
7850 Node* CodeStubAssembler::IsDebugActive() { | 7958 Node* CodeStubAssembler::IsDebugActive() { |
7851 Node* is_debug_active = Load( | 7959 Node* is_debug_active = Load( |
7852 MachineType::Uint8(), | 7960 MachineType::Uint8(), |
7853 ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); | 7961 ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); |
7854 return WordNotEqual(is_debug_active, Int32Constant(0)); | 7962 return WordNotEqual(is_debug_active, Int32Constant(0)); |
7855 } | 7963 } |
7856 | 7964 |
7857 } // namespace internal | 7965 } // namespace internal |
7858 } // namespace v8 | 7966 } // namespace v8 |
OLD | NEW |