Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Side by Side Diff: src/code-stub-assembler.cc

Issue 2539013002: [ic] Prevent KeyedStoreIC from being generic when storing doubles to integer typed arrays. (Closed)
Patch Set: Always use Float64RoundTiesEven instruction when available Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/compiler/code-assembler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/compiler/code-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698