| 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 | 4 |
| 5 #include "src/code-stub-assembler.h" | 5 #include "src/code-stub-assembler.h" |
| 6 #include "src/code-factory.h" | 6 #include "src/code-factory.h" |
| 7 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
| 8 #include "src/frames.h" | 8 #include "src/frames.h" |
| 9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
| 10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 } | 191 } |
| 192 | 192 |
| 193 Bind(&return_minus_x); | 193 Bind(&return_minus_x); |
| 194 var_x.Bind(Float64Neg(var_x.value())); | 194 var_x.Bind(Float64Neg(var_x.value())); |
| 195 Goto(&return_x); | 195 Goto(&return_x); |
| 196 | 196 |
| 197 Bind(&return_x); | 197 Bind(&return_x); |
| 198 return var_x.value(); | 198 return var_x.value(); |
| 199 } | 199 } |
| 200 | 200 |
| 201 Node* CodeStubAssembler::Float64RoundToEven(Node* x) { |
| 202 if (IsFloat64RoundTiesEvenSupported()) { |
| 203 return Float64RoundTiesEven(x); |
| 204 } |
| 205 // See ES#sec-touint8clamp for details. |
| 206 Node* f = Float64Floor(x); |
| 207 Node* f_and_half = Float64Add(f, Float64Constant(0.5)); |
| 208 |
| 209 Variable var_result(this, MachineRepresentation::kFloat64); |
| 210 Label return_f(this), return_f_plus_one(this), done(this); |
| 211 |
| 212 GotoIf(Float64LessThan(f_and_half, x), &return_f_plus_one); |
| 213 GotoIf(Float64LessThan(x, f_and_half), &return_f); |
| 214 { |
| 215 Node* f_mod_2 = Float64Mod(f, Float64Constant(2.0)); |
| 216 Branch(Float64Equal(f_mod_2, Float64Constant(0.0)), &return_f, |
| 217 &return_f_plus_one); |
| 218 } |
| 219 |
| 220 Bind(&return_f); |
| 221 var_result.Bind(f); |
| 222 Goto(&done); |
| 223 |
| 224 Bind(&return_f_plus_one); |
| 225 var_result.Bind(Float64Add(f, Float64Constant(1.0))); |
| 226 Goto(&done); |
| 227 |
| 228 Bind(&done); |
| 229 return var_result.value(); |
| 230 } |
| 231 |
| 201 Node* CodeStubAssembler::Float64Trunc(Node* x) { | 232 Node* CodeStubAssembler::Float64Trunc(Node* x) { |
| 202 if (IsFloat64RoundTruncateSupported()) { | 233 if (IsFloat64RoundTruncateSupported()) { |
| 203 return Float64RoundTruncate(x); | 234 return Float64RoundTruncate(x); |
| 204 } | 235 } |
| 205 | 236 |
| 206 Node* one = Float64Constant(1.0); | 237 Node* one = Float64Constant(1.0); |
| 207 Node* zero = Float64Constant(0.0); | 238 Node* zero = Float64Constant(0.0); |
| 208 Node* two_52 = Float64Constant(4503599627370496.0E0); | 239 Node* two_52 = Float64Constant(4503599627370496.0E0); |
| 209 Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); | 240 Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); |
| 210 | 241 |
| (...skipping 5076 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5287 Node* native_context = LoadNativeContext(context); | 5318 Node* native_context = LoadNativeContext(context); |
| 5288 Node* script_context_table = | 5319 Node* script_context_table = |
| 5289 LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); | 5320 LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); |
| 5290 | 5321 |
| 5291 int offset = | 5322 int offset = |
| 5292 ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; | 5323 ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; |
| 5293 return Load(MachineType::AnyTagged(), script_context_table, | 5324 return Load(MachineType::AnyTagged(), script_context_table, |
| 5294 IntPtrConstant(offset)); | 5325 IntPtrConstant(offset)); |
| 5295 } | 5326 } |
| 5296 | 5327 |
| 5297 Node* CodeStubAssembler::ClampedToUint8(Node* int32_value) { | |
| 5298 Label done(this); | |
| 5299 Node* int32_zero = Int32Constant(0); | |
| 5300 Node* int32_255 = Int32Constant(255); | |
| 5301 Variable var_value(this, MachineRepresentation::kWord32); | |
| 5302 var_value.Bind(int32_value); | |
| 5303 GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done); | |
| 5304 var_value.Bind(int32_zero); | |
| 5305 GotoIf(Int32LessThan(int32_value, int32_zero), &done); | |
| 5306 var_value.Bind(int32_255); | |
| 5307 Goto(&done); | |
| 5308 Bind(&done); | |
| 5309 return var_value.value(); | |
| 5310 } | |
| 5311 | |
| 5312 namespace { | 5328 namespace { |
| 5313 | 5329 |
| 5314 // Converts typed array elements kind to a machine representations. | 5330 // Converts typed array elements kind to a machine representations. |
| 5315 MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) { | 5331 MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) { |
| 5316 switch (kind) { | 5332 switch (kind) { |
| 5317 case UINT8_CLAMPED_ELEMENTS: | 5333 case UINT8_CLAMPED_ELEMENTS: |
| 5318 case UINT8_ELEMENTS: | 5334 case UINT8_ELEMENTS: |
| 5319 case INT8_ELEMENTS: | 5335 case INT8_ELEMENTS: |
| 5320 return MachineRepresentation::kWord8; | 5336 return MachineRepresentation::kWord8; |
| 5321 case UINT16_ELEMENTS: | 5337 case UINT16_ELEMENTS: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5334 } | 5350 } |
| 5335 } | 5351 } |
| 5336 | 5352 |
| 5337 } // namespace | 5353 } // namespace |
| 5338 | 5354 |
| 5339 void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, | 5355 void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, |
| 5340 Node* index, Node* value, | 5356 Node* index, Node* value, |
| 5341 ParameterMode mode) { | 5357 ParameterMode mode) { |
| 5342 if (IsFixedTypedArrayElementsKind(kind)) { | 5358 if (IsFixedTypedArrayElementsKind(kind)) { |
| 5343 if (kind == UINT8_CLAMPED_ELEMENTS) { | 5359 if (kind == UINT8_CLAMPED_ELEMENTS) { |
| 5344 value = ClampedToUint8(value); | 5360 #ifdef DEBUG |
| 5361 Assert(Word32Equal(value, Word32And(Int32Constant(0xff), value))); |
| 5362 #endif |
| 5345 } | 5363 } |
| 5346 Node* offset = ElementOffsetFromIndex(index, kind, mode, 0); | 5364 Node* offset = ElementOffsetFromIndex(index, kind, mode, 0); |
| 5347 MachineRepresentation rep = ElementsKindToMachineRepresentation(kind); | 5365 MachineRepresentation rep = ElementsKindToMachineRepresentation(kind); |
| 5348 StoreNoWriteBarrier(rep, elements, offset, value); | 5366 StoreNoWriteBarrier(rep, elements, offset, value); |
| 5349 return; | 5367 return; |
| 5350 } | 5368 } |
| 5351 | 5369 |
| 5352 WriteBarrierMode barrier_mode = | 5370 WriteBarrierMode barrier_mode = |
| 5353 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; | 5371 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; |
| 5354 if (IsFastDoubleElementsKind(kind)) { | 5372 if (IsFastDoubleElementsKind(kind)) { |
| 5355 // Make sure we do not store signalling NaNs into double arrays. | 5373 // Make sure we do not store signalling NaNs into double arrays. |
| 5356 value = Float64SilenceNaN(value); | 5374 value = Float64SilenceNaN(value); |
| 5357 StoreFixedDoubleArrayElement(elements, index, value, mode); | 5375 StoreFixedDoubleArrayElement(elements, index, value, mode); |
| 5358 } else { | 5376 } else { |
| 5359 StoreFixedArrayElement(elements, index, value, barrier_mode, mode); | 5377 StoreFixedArrayElement(elements, index, value, barrier_mode, mode); |
| 5360 } | 5378 } |
| 5361 } | 5379 } |
| 5362 | 5380 |
| 5381 Node* CodeStubAssembler::Int32ToUint8Clamped(Node* int32_value) { |
| 5382 Label done(this); |
| 5383 Node* int32_zero = Int32Constant(0); |
| 5384 Node* int32_255 = Int32Constant(255); |
| 5385 Variable var_value(this, MachineRepresentation::kWord32); |
| 5386 var_value.Bind(int32_value); |
| 5387 GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done); |
| 5388 var_value.Bind(int32_zero); |
| 5389 GotoIf(Int32LessThan(int32_value, int32_zero), &done); |
| 5390 var_value.Bind(int32_255); |
| 5391 Goto(&done); |
| 5392 Bind(&done); |
| 5393 return var_value.value(); |
| 5394 } |
| 5395 |
| 5396 Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) { |
| 5397 Label done(this); |
| 5398 Variable var_value(this, MachineRepresentation::kWord32); |
| 5399 var_value.Bind(Int32Constant(0)); |
| 5400 GotoIf(Float64LessThanOrEqual(float64_value, Float64Constant(0.0)), &done); |
| 5401 var_value.Bind(Int32Constant(255)); |
| 5402 GotoIf(Float64LessThanOrEqual(Float64Constant(255.0), float64_value), &done); |
| 5403 { |
| 5404 Node* rounded_value = Float64RoundToEven(float64_value); |
| 5405 var_value.Bind(TruncateFloat64ToWord32(rounded_value)); |
| 5406 Goto(&done); |
| 5407 } |
| 5408 Bind(&done); |
| 5409 return var_value.value(); |
| 5410 } |
| 5411 |
| 5412 Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( |
| 5413 Node* input, ElementsKind elements_kind, Label* bailout) { |
| 5414 DCHECK(IsFixedTypedArrayElementsKind(elements_kind)); |
| 5415 |
| 5416 MachineRepresentation rep; |
| 5417 switch (elements_kind) { |
| 5418 case UINT8_ELEMENTS: |
| 5419 case INT8_ELEMENTS: |
| 5420 case UINT16_ELEMENTS: |
| 5421 case INT16_ELEMENTS: |
| 5422 case UINT32_ELEMENTS: |
| 5423 case INT32_ELEMENTS: |
| 5424 case UINT8_CLAMPED_ELEMENTS: |
| 5425 rep = MachineRepresentation::kWord32; |
| 5426 break; |
| 5427 case FLOAT32_ELEMENTS: |
| 5428 rep = MachineRepresentation::kFloat32; |
| 5429 break; |
| 5430 case FLOAT64_ELEMENTS: |
| 5431 rep = MachineRepresentation::kFloat64; |
| 5432 break; |
| 5433 default: |
| 5434 UNREACHABLE(); |
| 5435 return nullptr; |
| 5436 } |
| 5437 |
| 5438 Variable var_result(this, rep); |
| 5439 Label done(this, &var_result), if_smi(this); |
| 5440 GotoIf(WordIsSmi(input), &if_smi); |
| 5441 // Try to convert a heap number to a Smi. |
| 5442 GotoUnless(IsHeapNumberMap(LoadMap(input)), bailout); |
| 5443 { |
| 5444 Node* value = LoadHeapNumberValue(input); |
| 5445 if (rep == MachineRepresentation::kWord32) { |
| 5446 if (elements_kind == UINT8_CLAMPED_ELEMENTS) { |
| 5447 value = Float64ToUint8Clamped(value); |
| 5448 } else { |
| 5449 value = TruncateFloat64ToWord32(value); |
| 5450 } |
| 5451 } else if (rep == MachineRepresentation::kFloat32) { |
| 5452 value = TruncateFloat64ToFloat32(value); |
| 5453 } else { |
| 5454 DCHECK_EQ(MachineRepresentation::kFloat64, rep); |
| 5455 } |
| 5456 var_result.Bind(value); |
| 5457 Goto(&done); |
| 5458 } |
| 5459 |
| 5460 Bind(&if_smi); |
| 5461 { |
| 5462 Node* value = SmiToWord32(input); |
| 5463 if (rep == MachineRepresentation::kFloat32) { |
| 5464 value = RoundInt32ToFloat32(value); |
| 5465 } else if (rep == MachineRepresentation::kFloat64) { |
| 5466 value = ChangeInt32ToFloat64(value); |
| 5467 } else { |
| 5468 DCHECK_EQ(MachineRepresentation::kWord32, rep); |
| 5469 if (elements_kind == UINT8_CLAMPED_ELEMENTS) { |
| 5470 value = Int32ToUint8Clamped(value); |
| 5471 } |
| 5472 } |
| 5473 var_result.Bind(value); |
| 5474 Goto(&done); |
| 5475 } |
| 5476 |
| 5477 Bind(&done); |
| 5478 return var_result.value(); |
| 5479 } |
| 5480 |
| 5363 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, | 5481 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, |
| 5364 bool is_jsarray, | 5482 bool is_jsarray, |
| 5365 ElementsKind elements_kind, | 5483 ElementsKind elements_kind, |
| 5366 KeyedAccessStoreMode store_mode, | 5484 KeyedAccessStoreMode store_mode, |
| 5367 Label* bailout) { | 5485 Label* bailout) { |
| 5368 Node* elements = LoadElements(object); | 5486 Node* elements = LoadElements(object); |
| 5369 if (IsFastSmiOrObjectElementsKind(elements_kind) && | 5487 if (IsFastSmiOrObjectElementsKind(elements_kind) && |
| 5370 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 5488 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| 5371 // Bailout in case of COW elements. | 5489 // Bailout in case of COW elements. |
| 5372 GotoIf(WordNotEqual(LoadMap(elements), | 5490 GotoIf(WordNotEqual(LoadMap(elements), |
| 5373 LoadRoot(Heap::kFixedArrayMapRootIndex)), | 5491 LoadRoot(Heap::kFixedArrayMapRootIndex)), |
| 5374 bailout); | 5492 bailout); |
| 5375 } | 5493 } |
| 5376 // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode(). | 5494 // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode(). |
| 5377 ParameterMode parameter_mode = INTPTR_PARAMETERS; | 5495 ParameterMode parameter_mode = INTPTR_PARAMETERS; |
| 5378 key = TryToIntptr(key, bailout); | 5496 key = TryToIntptr(key, bailout); |
| 5379 | 5497 |
| 5380 if (IsFixedTypedArrayElementsKind(elements_kind)) { | 5498 if (IsFixedTypedArrayElementsKind(elements_kind)) { |
| 5381 Label done(this); | 5499 Label done(this); |
| 5382 // TODO(ishell): call ToNumber() on value and don't bailout but be careful | 5500 // TODO(ishell): call ToNumber() on value and don't bailout but be careful |
| 5383 // to call it only once if we decide to bailout because of bounds checks. | 5501 // to call it only once if we decide to bailout because of bounds checks. |
| 5384 | 5502 |
| 5385 if (IsFixedFloatElementsKind(elements_kind)) { | 5503 value = PrepareValueForWriteToTypedArray(value, elements_kind, bailout); |
| 5386 // TODO(ishell): move float32 truncation into PrepareValueForWrite. | |
| 5387 value = PrepareValueForWrite(value, Representation::Double(), bailout); | |
| 5388 if (elements_kind == FLOAT32_ELEMENTS) { | |
| 5389 value = TruncateFloat64ToFloat32(value); | |
| 5390 } | |
| 5391 } else { | |
| 5392 // TODO(ishell): It's fine for word8/16/32 to truncate the result. | |
| 5393 value = TryToIntptr(value, bailout); | |
| 5394 } | |
| 5395 | 5504 |
| 5396 // There must be no allocations between the buffer load and | 5505 // There must be no allocations between the buffer load and |
| 5397 // and the actual store to backing store, because GC may decide that | 5506 // and the actual store to backing store, because GC may decide that |
| 5398 // the buffer is not alive or move the elements. | 5507 // the buffer is not alive or move the elements. |
| 5399 // TODO(ishell): introduce DisallowHeapAllocationCode scope here. | 5508 // TODO(ishell): introduce DisallowHeapAllocationCode scope here. |
| 5400 | 5509 |
| 5401 // Check if buffer has been neutered. | 5510 // Check if buffer has been neutered. |
| 5402 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); | 5511 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); |
| 5403 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, | 5512 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, |
| 5404 MachineType::Uint32()); | 5513 MachineType::Uint32()); |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5763 Heap::kTheHoleValueRootIndex); | 5872 Heap::kTheHoleValueRootIndex); |
| 5764 | 5873 |
| 5765 // Store the WeakCell in the feedback vector. | 5874 // Store the WeakCell in the feedback vector. |
| 5766 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 5875 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
| 5767 CodeStubAssembler::SMI_PARAMETERS); | 5876 CodeStubAssembler::SMI_PARAMETERS); |
| 5768 return cell; | 5877 return cell; |
| 5769 } | 5878 } |
| 5770 | 5879 |
| 5771 } // namespace internal | 5880 } // namespace internal |
| 5772 } // namespace v8 | 5881 } // namespace v8 |
| OLD | NEW |