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 5383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5394 Node* native_context = LoadNativeContext(context); | 5394 Node* native_context = LoadNativeContext(context); |
5395 Node* script_context_table = | 5395 Node* script_context_table = |
5396 LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); | 5396 LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); |
5397 | 5397 |
5398 int offset = | 5398 int offset = |
5399 ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; | 5399 ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; |
5400 return Load(MachineType::AnyTagged(), script_context_table, | 5400 return Load(MachineType::AnyTagged(), script_context_table, |
5401 IntPtrConstant(offset)); | 5401 IntPtrConstant(offset)); |
5402 } | 5402 } |
5403 | 5403 |
5404 Node* CodeStubAssembler::ClampedToUint8(Node* int32_value) { | |
Igor Sheludko
2016/11/30 09:32:05
I renamed it and moved down.
| |
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 { | 5404 namespace { |
5420 | 5405 |
5421 // Converts typed array elements kind to a machine representations. | 5406 // Converts typed array elements kind to a machine representations. |
5422 MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) { | 5407 MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) { |
5423 switch (kind) { | 5408 switch (kind) { |
5424 case UINT8_CLAMPED_ELEMENTS: | 5409 case UINT8_CLAMPED_ELEMENTS: |
5425 case UINT8_ELEMENTS: | 5410 case UINT8_ELEMENTS: |
5426 case INT8_ELEMENTS: | 5411 case INT8_ELEMENTS: |
5427 return MachineRepresentation::kWord8; | 5412 return MachineRepresentation::kWord8; |
5428 case UINT16_ELEMENTS: | 5413 case UINT16_ELEMENTS: |
(...skipping 12 matching lines...) Expand all Loading... | |
5441 } | 5426 } |
5442 } | 5427 } |
5443 | 5428 |
5444 } // namespace | 5429 } // namespace |
5445 | 5430 |
5446 void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, | 5431 void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, |
5447 Node* index, Node* value, | 5432 Node* index, Node* value, |
5448 ParameterMode mode) { | 5433 ParameterMode mode) { |
5449 if (IsFixedTypedArrayElementsKind(kind)) { | 5434 if (IsFixedTypedArrayElementsKind(kind)) { |
5450 if (kind == UINT8_CLAMPED_ELEMENTS) { | 5435 if (kind == UINT8_CLAMPED_ELEMENTS) { |
5451 value = ClampedToUint8(value); | 5436 CSA_ASSERT(this, |
5437 Word32Equal(value, Word32And(Int32Constant(0xff), value))); | |
5452 } | 5438 } |
5453 Node* offset = ElementOffsetFromIndex(index, kind, mode, 0); | 5439 Node* offset = ElementOffsetFromIndex(index, kind, mode, 0); |
5454 MachineRepresentation rep = ElementsKindToMachineRepresentation(kind); | 5440 MachineRepresentation rep = ElementsKindToMachineRepresentation(kind); |
5455 StoreNoWriteBarrier(rep, elements, offset, value); | 5441 StoreNoWriteBarrier(rep, elements, offset, value); |
5456 return; | 5442 return; |
5457 } | 5443 } |
5458 | 5444 |
5459 WriteBarrierMode barrier_mode = | 5445 WriteBarrierMode barrier_mode = |
5460 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; | 5446 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; |
5461 if (IsFastDoubleElementsKind(kind)) { | 5447 if (IsFastDoubleElementsKind(kind)) { |
5462 // Make sure we do not store signalling NaNs into double arrays. | 5448 // Make sure we do not store signalling NaNs into double arrays. |
5463 value = Float64SilenceNaN(value); | 5449 value = Float64SilenceNaN(value); |
5464 StoreFixedDoubleArrayElement(elements, index, value, mode); | 5450 StoreFixedDoubleArrayElement(elements, index, value, mode); |
5465 } else { | 5451 } else { |
5466 StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode); | 5452 StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode); |
5467 } | 5453 } |
5468 } | 5454 } |
5469 | 5455 |
5456 Node* CodeStubAssembler::Int32ToUint8Clamped(Node* int32_value) { | |
5457 Label done(this); | |
5458 Node* int32_zero = Int32Constant(0); | |
5459 Node* int32_255 = Int32Constant(255); | |
5460 Variable var_value(this, MachineRepresentation::kWord32); | |
5461 var_value.Bind(int32_value); | |
5462 GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done); | |
5463 var_value.Bind(int32_zero); | |
5464 GotoIf(Int32LessThan(int32_value, int32_zero), &done); | |
5465 var_value.Bind(int32_255); | |
5466 Goto(&done); | |
5467 Bind(&done); | |
5468 return var_value.value(); | |
5469 } | |
5470 | |
5471 Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) { | |
5472 Label done(this); | |
5473 Variable var_value(this, MachineRepresentation::kWord32); | |
5474 var_value.Bind(Int32Constant(0)); | |
5475 GotoIf(Float64LessThanOrEqual(float64_value, Float64Constant(0.0)), &done); | |
5476 var_value.Bind(Int32Constant(255)); | |
5477 GotoIf(Float64LessThanOrEqual(Float64Constant(255.0), float64_value), &done); | |
5478 { | |
5479 Node* rounded_value = Float64RoundTiesEven(float64_value); | |
5480 var_value.Bind(TruncateFloat64ToWord32(rounded_value)); | |
5481 Goto(&done); | |
5482 } | |
5483 Bind(&done); | |
5484 return var_value.value(); | |
5485 } | |
5486 | |
5487 Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( | |
5488 Node* input, ElementsKind elements_kind, Label* bailout) { | |
5489 DCHECK(IsFixedTypedArrayElementsKind(elements_kind)); | |
5490 | |
5491 MachineRepresentation rep; | |
5492 switch (elements_kind) { | |
5493 case UINT8_ELEMENTS: | |
5494 case INT8_ELEMENTS: | |
5495 case UINT16_ELEMENTS: | |
5496 case INT16_ELEMENTS: | |
5497 case UINT32_ELEMENTS: | |
5498 case INT32_ELEMENTS: | |
5499 case UINT8_CLAMPED_ELEMENTS: | |
5500 rep = MachineRepresentation::kWord32; | |
5501 break; | |
5502 case FLOAT32_ELEMENTS: | |
5503 rep = MachineRepresentation::kFloat32; | |
5504 break; | |
5505 case FLOAT64_ELEMENTS: | |
5506 rep = MachineRepresentation::kFloat64; | |
5507 break; | |
5508 default: | |
5509 UNREACHABLE(); | |
5510 return nullptr; | |
5511 } | |
5512 | |
5513 Variable var_result(this, rep); | |
5514 Label done(this, &var_result), if_smi(this); | |
5515 GotoIf(TaggedIsSmi(input), &if_smi); | |
5516 // Try to convert a heap number to a Smi. | |
5517 GotoUnless(IsHeapNumberMap(LoadMap(input)), bailout); | |
5518 { | |
5519 Node* value = LoadHeapNumberValue(input); | |
5520 if (rep == MachineRepresentation::kWord32) { | |
5521 if (elements_kind == UINT8_CLAMPED_ELEMENTS) { | |
5522 value = Float64ToUint8Clamped(value); | |
5523 } else { | |
5524 value = TruncateFloat64ToWord32(value); | |
5525 } | |
5526 } else if (rep == MachineRepresentation::kFloat32) { | |
5527 value = TruncateFloat64ToFloat32(value); | |
5528 } else { | |
5529 DCHECK_EQ(MachineRepresentation::kFloat64, rep); | |
5530 } | |
5531 var_result.Bind(value); | |
5532 Goto(&done); | |
5533 } | |
5534 | |
5535 Bind(&if_smi); | |
5536 { | |
5537 Node* value = SmiToWord32(input); | |
5538 if (rep == MachineRepresentation::kFloat32) { | |
5539 value = RoundInt32ToFloat32(value); | |
5540 } else if (rep == MachineRepresentation::kFloat64) { | |
5541 value = ChangeInt32ToFloat64(value); | |
5542 } else { | |
5543 DCHECK_EQ(MachineRepresentation::kWord32, rep); | |
5544 if (elements_kind == UINT8_CLAMPED_ELEMENTS) { | |
5545 value = Int32ToUint8Clamped(value); | |
5546 } | |
5547 } | |
5548 var_result.Bind(value); | |
5549 Goto(&done); | |
5550 } | |
5551 | |
5552 Bind(&done); | |
5553 return var_result.value(); | |
5554 } | |
5555 | |
5470 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, | 5556 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, |
5471 bool is_jsarray, | 5557 bool is_jsarray, |
5472 ElementsKind elements_kind, | 5558 ElementsKind elements_kind, |
5473 KeyedAccessStoreMode store_mode, | 5559 KeyedAccessStoreMode store_mode, |
5474 Label* bailout) { | 5560 Label* bailout) { |
5475 Node* elements = LoadElements(object); | 5561 Node* elements = LoadElements(object); |
5476 if (IsFastSmiOrObjectElementsKind(elements_kind) && | 5562 if (IsFastSmiOrObjectElementsKind(elements_kind) && |
5477 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 5563 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
5478 // Bailout in case of COW elements. | 5564 // Bailout in case of COW elements. |
5479 GotoIf(WordNotEqual(LoadMap(elements), | 5565 GotoIf(WordNotEqual(LoadMap(elements), |
5480 LoadRoot(Heap::kFixedArrayMapRootIndex)), | 5566 LoadRoot(Heap::kFixedArrayMapRootIndex)), |
5481 bailout); | 5567 bailout); |
5482 } | 5568 } |
5483 // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode(). | 5569 // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode(). |
5484 ParameterMode parameter_mode = INTPTR_PARAMETERS; | 5570 ParameterMode parameter_mode = INTPTR_PARAMETERS; |
5485 key = TryToIntptr(key, bailout); | 5571 key = TryToIntptr(key, bailout); |
5486 | 5572 |
5487 if (IsFixedTypedArrayElementsKind(elements_kind)) { | 5573 if (IsFixedTypedArrayElementsKind(elements_kind)) { |
5488 Label done(this); | 5574 Label done(this); |
5489 // TODO(ishell): call ToNumber() on value and don't bailout but be careful | 5575 // 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. | 5576 // to call it only once if we decide to bailout because of bounds checks. |
5491 | 5577 |
5492 if (IsFixedFloatElementsKind(elements_kind)) { | 5578 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 | 5579 |
5503 // There must be no allocations between the buffer load and | 5580 // There must be no allocations between the buffer load and |
5504 // and the actual store to backing store, because GC may decide that | 5581 // and the actual store to backing store, because GC may decide that |
5505 // the buffer is not alive or move the elements. | 5582 // the buffer is not alive or move the elements. |
5506 // TODO(ishell): introduce DisallowHeapAllocationCode scope here. | 5583 // TODO(ishell): introduce DisallowHeapAllocationCode scope here. |
5507 | 5584 |
5508 // Check if buffer has been neutered. | 5585 // Check if buffer has been neutered. |
5509 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); | 5586 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); |
5510 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, | 5587 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, |
5511 MachineType::Uint32()); | 5588 MachineType::Uint32()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5545 Node* length = is_jsarray ? LoadObjectField(object, JSArray::kLengthOffset) | 5622 Node* length = is_jsarray ? LoadObjectField(object, JSArray::kLengthOffset) |
5546 : LoadFixedArrayBaseLength(elements); | 5623 : LoadFixedArrayBaseLength(elements); |
5547 length = UntagParameter(length, parameter_mode); | 5624 length = UntagParameter(length, parameter_mode); |
5548 | 5625 |
5549 // In case value is stored into a fast smi array, assure that the value is | 5626 // 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 | 5627 // a smi before manipulating the backing store. Otherwise the backing store |
5551 // may be left in an invalid state. | 5628 // may be left in an invalid state. |
5552 if (IsFastSmiElementsKind(elements_kind)) { | 5629 if (IsFastSmiElementsKind(elements_kind)) { |
5553 GotoUnless(TaggedIsSmi(value), bailout); | 5630 GotoUnless(TaggedIsSmi(value), bailout); |
5554 } else if (IsFastDoubleElementsKind(elements_kind)) { | 5631 } else if (IsFastDoubleElementsKind(elements_kind)) { |
5555 value = PrepareValueForWrite(value, Representation::Double(), bailout); | 5632 value = TryTaggedToFloat64(value, bailout); |
5556 } | 5633 } |
5557 | 5634 |
5558 if (IsGrowStoreMode(store_mode)) { | 5635 if (IsGrowStoreMode(store_mode)) { |
5559 elements = CheckForCapacityGrow(object, elements, elements_kind, length, | 5636 elements = CheckForCapacityGrow(object, elements, elements_kind, length, |
5560 key, parameter_mode, is_jsarray, bailout); | 5637 key, parameter_mode, is_jsarray, bailout); |
5561 } else { | 5638 } else { |
5562 GotoUnless(UintPtrLessThan(key, length), bailout); | 5639 GotoUnless(UintPtrLessThan(key, length), bailout); |
5563 | 5640 |
5564 if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW) && | 5641 if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW) && |
5565 IsFastSmiOrObjectElementsKind(elements_kind)) { | 5642 IsFastSmiOrObjectElementsKind(elements_kind)) { |
(...skipping 2283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7849 | 7926 |
7850 Node* CodeStubAssembler::IsDebugActive() { | 7927 Node* CodeStubAssembler::IsDebugActive() { |
7851 Node* is_debug_active = Load( | 7928 Node* is_debug_active = Load( |
7852 MachineType::Uint8(), | 7929 MachineType::Uint8(), |
7853 ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); | 7930 ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); |
7854 return WordNotEqual(is_debug_active, Int32Constant(0)); | 7931 return WordNotEqual(is_debug_active, Int32Constant(0)); |
7855 } | 7932 } |
7856 | 7933 |
7857 } // namespace internal | 7934 } // namespace internal |
7858 } // namespace v8 | 7935 } // namespace v8 |
OLD | NEW |