Chromium Code Reviews| 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 |