2017-07-13 09:55:16 +00:00
|
|
|
// Copyright 2017 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
2017-08-30 12:09:00 +00:00
|
|
|
#include "src/base/utils/random-number-generator.h"
|
2019-05-21 09:30:15 +00:00
|
|
|
#include "src/codegen/assembler-inl.h"
|
|
|
|
#include "src/codegen/code-stub-assembler.h"
|
|
|
|
#include "src/codegen/optimized-compilation-info.h"
|
2018-11-12 14:12:52 +00:00
|
|
|
#include "src/compiler/backend/code-generator.h"
|
|
|
|
#include "src/compiler/backend/instruction.h"
|
2017-07-13 09:55:16 +00:00
|
|
|
#include "src/compiler/linkage.h"
|
2019-05-22 07:55:37 +00:00
|
|
|
#include "src/execution/isolate.h"
|
2018-12-17 17:01:48 +00:00
|
|
|
#include "src/objects/heap-number-inl.h"
|
2019-05-23 08:51:46 +00:00
|
|
|
#include "src/objects/objects-inl.h"
|
2018-11-03 00:13:22 +00:00
|
|
|
#include "src/objects/smi.h"
|
2017-07-13 09:55:16 +00:00
|
|
|
|
|
|
|
#include "test/cctest/cctest.h"
|
2017-10-11 10:22:40 +00:00
|
|
|
#include "test/cctest/compiler/code-assembler-tester.h"
|
2017-08-30 12:09:00 +00:00
|
|
|
#include "test/cctest/compiler/function-tester.h"
|
2017-07-13 09:55:16 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace compiler {
|
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
#define __ assembler.
|
|
|
|
|
2017-08-30 12:09:00 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
int GetSlotSizeInBytes(MachineRepresentation rep) {
|
|
|
|
switch (rep) {
|
|
|
|
case MachineRepresentation::kTagged:
|
2019-02-14 13:01:52 +00:00
|
|
|
// Spill slots for tagged values are always uncompressed.
|
|
|
|
return kSystemPointerSize;
|
2017-08-30 12:09:00 +00:00
|
|
|
case MachineRepresentation::kFloat32:
|
2019-02-14 13:01:52 +00:00
|
|
|
return kSystemPointerSize;
|
2017-08-30 12:09:00 +00:00
|
|
|
case MachineRepresentation::kFloat64:
|
|
|
|
return kDoubleSize;
|
|
|
|
case MachineRepresentation::kSimd128:
|
|
|
|
return kSimd128Size;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
// Forward declaration.
|
2018-02-09 19:19:25 +00:00
|
|
|
Handle<Code> BuildTeardownFunction(Isolate* isolate,
|
|
|
|
CallDescriptor* call_descriptor,
|
2017-10-17 17:28:35 +00:00
|
|
|
std::vector<AllocatedOperand> parameters);
|
2017-10-11 10:22:40 +00:00
|
|
|
|
|
|
|
// Build the `setup` function. It takes a code object and a FixedArray as
|
|
|
|
// parameters and calls the former while passing it each element of the array as
|
|
|
|
// arguments:
|
|
|
|
// ~~~
|
|
|
|
// FixedArray setup(CodeObject* test, FixedArray state_in) {
|
2018-09-07 10:21:41 +00:00
|
|
|
// FixedArray state_out = AllocateZeroedFixedArray(state_in.length());
|
2017-10-11 10:22:40 +00:00
|
|
|
// // `test` will tail-call to its first parameter which will be `teardown`.
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// return test(teardown, state_out, state_in[0], state_in[1],
|
|
|
|
// state_in[2], ...);
|
2017-10-11 10:22:40 +00:00
|
|
|
// }
|
|
|
|
// ~~~
|
|
|
|
//
|
|
|
|
// This function needs to convert each element of the FixedArray to raw unboxed
|
|
|
|
// values to pass to the `test` function. The array will have been created using
|
|
|
|
// `GenerateInitialState()` and needs to be converted in the following way:
|
|
|
|
//
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// | Parameter type | FixedArray element | Conversion |
|
|
|
|
// |----------------+---------------------+------------------------------------|
|
|
|
|
// | kTagged | Smi | None. |
|
|
|
|
// | kFloat32 | HeapNumber | Load value and convert to Float32. |
|
|
|
|
// | kFloat64 | HeapNumber | Load value. |
|
|
|
|
// | kSimd128 | FixedArray<Smi>[4] | Untag each Smi and write the |
|
|
|
|
// | | | results into lanes of a new |
|
|
|
|
// | | | 128-bit vector. |
|
2017-10-11 10:22:40 +00:00
|
|
|
//
|
2018-02-09 19:19:25 +00:00
|
|
|
Handle<Code> BuildSetupFunction(Isolate* isolate,
|
|
|
|
CallDescriptor* call_descriptor,
|
2017-10-17 17:28:35 +00:00
|
|
|
std::vector<AllocatedOperand> parameters) {
|
2018-04-05 16:25:41 +00:00
|
|
|
CodeAssemblerTester tester(isolate, 2, Code::BUILTIN, "setup");
|
2017-10-11 10:22:40 +00:00
|
|
|
CodeStubAssembler assembler(tester.state());
|
|
|
|
std::vector<Node*> params;
|
|
|
|
// The first parameter is always the callee.
|
|
|
|
params.push_back(__ Parameter(0));
|
2018-02-09 19:19:25 +00:00
|
|
|
params.push_back(__ HeapConstant(
|
|
|
|
BuildTeardownFunction(isolate, call_descriptor, parameters)));
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// First allocate the FixedArray which will hold the final results. Here we
|
|
|
|
// should take care of all allocations, meaning we allocate HeapNumbers and
|
|
|
|
// FixedArrays representing Simd128 values.
|
2018-09-07 10:21:41 +00:00
|
|
|
TNode<FixedArray> state_out =
|
|
|
|
__ AllocateZeroedFixedArray(__ IntPtrConstant(parameters.size()));
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
for (int i = 0; i < static_cast<int>(parameters.size()); i++) {
|
|
|
|
switch (parameters[i].representation()) {
|
|
|
|
case MachineRepresentation::kTagged:
|
|
|
|
break;
|
|
|
|
case MachineRepresentation::kFloat32:
|
|
|
|
case MachineRepresentation::kFloat64:
|
|
|
|
__ StoreFixedArrayElement(state_out, i, __ AllocateHeapNumber());
|
|
|
|
break;
|
|
|
|
case MachineRepresentation::kSimd128: {
|
2018-09-07 10:21:41 +00:00
|
|
|
TNode<FixedArray> vector =
|
|
|
|
__ AllocateZeroedFixedArray(__ IntPtrConstant(4));
|
2018-04-05 16:25:41 +00:00
|
|
|
for (int lane = 0; lane < 4; lane++) {
|
|
|
|
__ StoreFixedArrayElement(vector, lane, __ SmiConstant(0));
|
|
|
|
}
|
|
|
|
__ StoreFixedArrayElement(state_out, i, vector);
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
params.push_back(state_out);
|
|
|
|
// Then take each element of the initial state and pass them as arguments.
|
2018-08-07 13:26:55 +00:00
|
|
|
TNode<FixedArray> state_in = __ Cast(__ Parameter(1));
|
2017-10-17 17:28:35 +00:00
|
|
|
for (int i = 0; i < static_cast<int>(parameters.size()); i++) {
|
2017-10-11 10:22:40 +00:00
|
|
|
Node* element = __ LoadFixedArrayElement(state_in, __ IntPtrConstant(i));
|
|
|
|
// Unbox all elements before passing them as arguments.
|
2017-10-17 17:28:35 +00:00
|
|
|
switch (parameters[i].representation()) {
|
2017-10-11 10:22:40 +00:00
|
|
|
// Tagged parameters are Smis, they do not need unboxing.
|
|
|
|
case MachineRepresentation::kTagged:
|
|
|
|
break;
|
|
|
|
case MachineRepresentation::kFloat32:
|
|
|
|
element = __ TruncateFloat64ToFloat32(__ LoadHeapNumberValue(element));
|
|
|
|
break;
|
|
|
|
case MachineRepresentation::kFloat64:
|
|
|
|
element = __ LoadHeapNumberValue(element);
|
|
|
|
break;
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
case MachineRepresentation::kSimd128: {
|
|
|
|
Node* vector = tester.raw_assembler_for_testing()->AddNode(
|
|
|
|
tester.raw_assembler_for_testing()->machine()->I32x4Splat(),
|
|
|
|
__ Int32Constant(0));
|
|
|
|
for (int lane = 0; lane < 4; lane++) {
|
2018-03-28 14:05:31 +00:00
|
|
|
TNode<Int32T> lane_value = __ LoadAndUntagToWord32FixedArrayElement(
|
2018-11-22 09:30:40 +00:00
|
|
|
__ CAST(element), __ IntPtrConstant(lane));
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
vector = tester.raw_assembler_for_testing()->AddNode(
|
|
|
|
tester.raw_assembler_for_testing()->machine()->I32x4ReplaceLane(
|
|
|
|
lane),
|
|
|
|
vector, lane_value);
|
|
|
|
}
|
|
|
|
element = vector;
|
|
|
|
break;
|
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
params.push_back(element);
|
|
|
|
}
|
|
|
|
__ Return(tester.raw_assembler_for_testing()->AddNode(
|
2018-02-09 19:19:25 +00:00
|
|
|
tester.raw_assembler_for_testing()->common()->Call(call_descriptor),
|
2017-10-11 10:22:40 +00:00
|
|
|
static_cast<int>(params.size()), params.data()));
|
|
|
|
return tester.GenerateCodeCloseAndEscape();
|
|
|
|
}
|
|
|
|
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// Build the `teardown` function. It takes a FixedArray as argument, fills it
|
|
|
|
// with the rest of its parameters and returns it. The parameters need to be
|
|
|
|
// consistent with `parameters`.
|
2017-10-11 10:22:40 +00:00
|
|
|
// ~~~
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// FixedArray teardown(CodeObject* /* unused */, FixedArray result,
|
2017-10-11 10:22:40 +00:00
|
|
|
// // Tagged registers.
|
2018-12-25 00:19:47 +00:00
|
|
|
// Object r0, Object r1, ...,
|
2017-10-11 10:22:40 +00:00
|
|
|
// // FP registers.
|
|
|
|
// Float32 s0, Float64 d1, ...,
|
|
|
|
// // Mixed stack slots.
|
2018-12-25 00:19:47 +00:00
|
|
|
// Float64 mem0, Object mem1, Float32 mem2, ...) {
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// result[0] = r0;
|
|
|
|
// result[1] = r1;
|
|
|
|
// ...
|
|
|
|
// result[..] = s0;
|
|
|
|
// ...
|
|
|
|
// result[..] = mem0;
|
|
|
|
// ...
|
|
|
|
// return result;
|
2017-10-11 10:22:40 +00:00
|
|
|
// }
|
|
|
|
// ~~~
|
|
|
|
//
|
|
|
|
// This function needs to convert its parameters into values fit for a
|
|
|
|
// FixedArray, essentially reverting what the `setup` function did:
|
|
|
|
//
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// | Parameter type | Parameter value | Conversion |
|
|
|
|
// |----------------+-------------------+--------------------------------------|
|
|
|
|
// | kTagged | Smi or HeapNumber | None. |
|
|
|
|
// | kFloat32 | Raw Float32 | Convert to Float64. |
|
|
|
|
// | kFloat64 | Raw Float64 | None. |
|
|
|
|
// | kSimd128 | Raw Simd128 | Split into 4 Word32 values and tag |
|
|
|
|
// | | | them. |
|
2017-10-11 10:22:40 +00:00
|
|
|
//
|
|
|
|
// Note that it is possible for a `kTagged` value to go from a Smi to a
|
|
|
|
// HeapNumber. This is because `AssembleMove` will allocate a new HeapNumber if
|
|
|
|
// it is asked to move a FP constant to a tagged register or slot.
|
|
|
|
//
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// Finally, it is important that this function does not call `RecordWrite` which
|
|
|
|
// is why "setup" is in charge of all allocations and we are using
|
2019-05-15 08:45:36 +00:00
|
|
|
// UNSAFE_SKIP_WRITE_BARRIER. The reason for this is that `RecordWrite` may
|
|
|
|
// clobber the top 64 bits of Simd128 registers. This is the case on x64, ia32
|
|
|
|
// and Arm64 for example.
|
2018-02-09 19:19:25 +00:00
|
|
|
Handle<Code> BuildTeardownFunction(Isolate* isolate,
|
|
|
|
CallDescriptor* call_descriptor,
|
2017-10-17 17:28:35 +00:00
|
|
|
std::vector<AllocatedOperand> parameters) {
|
2018-04-05 16:25:41 +00:00
|
|
|
CodeAssemblerTester tester(isolate, call_descriptor, "teardown");
|
2017-10-11 10:22:40 +00:00
|
|
|
CodeStubAssembler assembler(tester.state());
|
2018-08-07 13:26:55 +00:00
|
|
|
TNode<FixedArray> result_array = __ Cast(__ Parameter(1));
|
2017-10-17 17:28:35 +00:00
|
|
|
for (int i = 0; i < static_cast<int>(parameters.size()); i++) {
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// The first argument is not used and the second is "result_array".
|
|
|
|
Node* param = __ Parameter(i + 2);
|
2017-10-17 17:28:35 +00:00
|
|
|
switch (parameters[i].representation()) {
|
2017-10-11 10:22:40 +00:00
|
|
|
case MachineRepresentation::kTagged:
|
2019-05-15 08:45:36 +00:00
|
|
|
__ StoreFixedArrayElement(result_array, i, param,
|
|
|
|
UNSAFE_SKIP_WRITE_BARRIER);
|
2017-10-11 10:22:40 +00:00
|
|
|
break;
|
|
|
|
// Box FP values into HeapNumbers.
|
|
|
|
case MachineRepresentation::kFloat32:
|
|
|
|
param =
|
|
|
|
tester.raw_assembler_for_testing()->ChangeFloat32ToFloat64(param);
|
2018-02-20 16:28:51 +00:00
|
|
|
V8_FALLTHROUGH;
|
2017-10-11 10:22:40 +00:00
|
|
|
case MachineRepresentation::kFloat64:
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
__ StoreObjectFieldNoWriteBarrier(
|
|
|
|
__ LoadFixedArrayElement(result_array, i), HeapNumber::kValueOffset,
|
|
|
|
param, MachineRepresentation::kFloat64);
|
|
|
|
break;
|
|
|
|
case MachineRepresentation::kSimd128: {
|
2018-08-07 13:26:55 +00:00
|
|
|
TNode<FixedArray> vector =
|
|
|
|
__ Cast(__ LoadFixedArrayElement(result_array, i));
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
for (int lane = 0; lane < 4; lane++) {
|
|
|
|
Node* lane_value =
|
2018-02-23 13:46:00 +00:00
|
|
|
__ SmiFromInt32(tester.raw_assembler_for_testing()->AddNode(
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
tester.raw_assembler_for_testing()
|
|
|
|
->machine()
|
|
|
|
->I32x4ExtractLane(lane),
|
|
|
|
param));
|
|
|
|
__ StoreFixedArrayElement(vector, lane, lane_value,
|
2019-05-15 08:45:36 +00:00
|
|
|
UNSAFE_SKIP_WRITE_BARRIER);
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
break;
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
__ Return(result_array);
|
|
|
|
return tester.GenerateCodeCloseAndEscape();
|
|
|
|
}
|
|
|
|
|
2017-10-17 17:28:35 +00:00
|
|
|
// Print the content of `value`, representing the register or stack slot
|
|
|
|
// described by `operand`.
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
void PrintStateValue(std::ostream& os, Isolate* isolate, Handle<Object> value,
|
2017-10-17 17:28:35 +00:00
|
|
|
AllocatedOperand operand) {
|
|
|
|
switch (operand.representation()) {
|
|
|
|
case MachineRepresentation::kTagged:
|
|
|
|
if (value->IsSmi()) {
|
2019-05-23 07:47:44 +00:00
|
|
|
os << Smi::cast(*value).value();
|
2017-10-17 17:28:35 +00:00
|
|
|
} else {
|
|
|
|
os << value->Number();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MachineRepresentation::kFloat32:
|
|
|
|
case MachineRepresentation::kFloat64:
|
|
|
|
os << value->Number();
|
|
|
|
break;
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
case MachineRepresentation::kSimd128: {
|
2018-11-25 02:24:43 +00:00
|
|
|
FixedArray vector = FixedArray::cast(*value);
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
os << "[";
|
|
|
|
for (int lane = 0; lane < 4; lane++) {
|
2019-05-23 07:47:44 +00:00
|
|
|
os << Smi::cast(vector.get(lane)).value();
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
if (lane < 3) {
|
|
|
|
os << ", ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
os << "]";
|
|
|
|
break;
|
|
|
|
}
|
2017-10-17 17:28:35 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
os << " (" << operand.representation() << " ";
|
|
|
|
if (operand.location_kind() == AllocatedOperand::REGISTER) {
|
|
|
|
os << "register";
|
|
|
|
} else {
|
|
|
|
DCHECK_EQ(operand.location_kind(), AllocatedOperand::STACK_SLOT);
|
|
|
|
os << "stack slot";
|
|
|
|
}
|
|
|
|
os << ")";
|
|
|
|
}
|
|
|
|
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
bool TestSimd128Moves() {
|
|
|
|
return CpuFeatures::SupportsWasmSimd128();
|
|
|
|
}
|
|
|
|
|
2017-08-30 12:09:00 +00:00
|
|
|
} // namespace
|
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
#undef __
|
|
|
|
|
|
|
|
// Representation of a test environment. It describes a set of registers, stack
|
|
|
|
// slots and constants available to the CodeGeneratorTester to perform moves
|
|
|
|
// with. It has the ability to randomly generate lists of moves and run the code
|
|
|
|
// generated by the CodeGeneratorTester.
|
2017-08-30 12:09:00 +00:00
|
|
|
//
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// The following representations are tested:
|
2017-08-30 12:09:00 +00:00
|
|
|
// - kTagged
|
|
|
|
// - kFloat32
|
|
|
|
// - kFloat64
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// - kSimd128 (if supported)
|
2017-08-30 12:09:00 +00:00
|
|
|
// There is no need to test using Word32 or Word64 as they are the same as
|
|
|
|
// Tagged as far as the code generator is concerned.
|
2017-10-11 10:22:40 +00:00
|
|
|
//
|
|
|
|
// Testing the generated code is achieved by wrapping it around `setup` and
|
|
|
|
// `teardown` functions, written using the CodeStubAssembler. The key idea here
|
|
|
|
// is that `teardown` and the generated code share the same custom
|
|
|
|
// CallDescriptor. This descriptor assigns parameters to either registers or
|
|
|
|
// stack slot of a given representation and therefore essentially describes the
|
|
|
|
// environment.
|
|
|
|
//
|
|
|
|
// What happens is the following:
|
|
|
|
//
|
|
|
|
// - The `setup` function receives a FixedArray as the initial state. It
|
|
|
|
// unpacks it and passes each element as arguments to the generated code
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// `test`. We also pass the `teardown` function as a first argument as well
|
|
|
|
// as a newly allocated FixedArray as a second argument which will hold the
|
|
|
|
// final results. Thanks to the custom CallDescriptor, registers and stack
|
|
|
|
// slots get initialised according to the content of the initial FixedArray.
|
2017-10-11 10:22:40 +00:00
|
|
|
//
|
|
|
|
// - The `test` function performs the list of moves on its parameters and
|
|
|
|
// eventually tail-calls to its first parameter, which is the `teardown`
|
|
|
|
// function.
|
|
|
|
//
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// - The `teardown` function receives the final results as a FixedArray, fills
|
|
|
|
// it with the rest of its arguments and returns it. Thanks to the
|
|
|
|
// tail-call, this is as if the `setup` function called `teardown` directly,
|
|
|
|
// except now moves were performed!
|
2017-10-11 10:22:40 +00:00
|
|
|
//
|
|
|
|
// .----------------setup--------------------------.
|
|
|
|
// | Take a FixedArray as parameters with |
|
|
|
|
// | all the initial values of registers |
|
|
|
|
// | and stack slots. | <- CodeStubAssembler
|
|
|
|
// | |
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// | Allocate a new FixedArray `result` with |
|
|
|
|
// | initial values. |
|
|
|
|
// | |
|
|
|
|
// | Call test(teardown, result, state[0], |
|
|
|
|
// | state[1], state[2], ...); |
|
2017-10-11 10:22:40 +00:00
|
|
|
// '-----------------------------------------------'
|
|
|
|
// |
|
|
|
|
// V
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// .----------------test-------------------------------.
|
|
|
|
// | - Move(param3, param42); |
|
|
|
|
// | - Swap(param64, param4); |
|
|
|
|
// | - Move(param2, param6); | <- CodeGeneratorTester
|
|
|
|
// | ... |
|
|
|
|
// | |
|
|
|
|
// | // "teardown" is the first parameter as well as |
|
|
|
|
// | // the callee. |
|
|
|
|
// | TailCall teardown(teardown, result, param2, ...); |
|
|
|
|
// '---------------------------------------------------'
|
2017-10-11 10:22:40 +00:00
|
|
|
// |
|
|
|
|
// V
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// .----------------teardown---------------------------.
|
|
|
|
// | Fill in the incoming `result` FixedArray with all |
|
|
|
|
// | parameters and return it. | <- CodeStubAssembler
|
|
|
|
// '---------------------------------------------------'
|
2017-10-11 10:22:40 +00:00
|
|
|
|
|
|
|
class TestEnvironment : public HandleAndZoneScope {
|
2017-07-13 09:55:16 +00:00
|
|
|
public:
|
2017-10-11 10:22:40 +00:00
|
|
|
// These constants may be tuned to experiment with different environments.
|
|
|
|
|
2018-10-25 12:01:12 +00:00
|
|
|
#ifdef V8_TARGET_ARCH_IA32
|
2018-10-02 14:24:19 +00:00
|
|
|
static constexpr int kGeneralRegisterCount = 3;
|
|
|
|
#else
|
2017-10-23 06:49:35 +00:00
|
|
|
static constexpr int kGeneralRegisterCount = 4;
|
2018-10-02 14:24:19 +00:00
|
|
|
#endif
|
2017-10-23 06:49:35 +00:00
|
|
|
static constexpr int kDoubleRegisterCount = 6;
|
2017-10-11 10:22:40 +00:00
|
|
|
|
2017-10-23 06:49:35 +00:00
|
|
|
static constexpr int kTaggedSlotCount = 64;
|
|
|
|
static constexpr int kFloat32SlotCount = 64;
|
|
|
|
static constexpr int kFloat64SlotCount = 64;
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
static constexpr int kSimd128SlotCount = 16;
|
2017-10-11 10:22:40 +00:00
|
|
|
|
|
|
|
// TODO(all): Test all types of constants (e.g. ExternalReference and
|
|
|
|
// HeapObject).
|
2017-10-23 06:49:35 +00:00
|
|
|
static constexpr int kSmiConstantCount = 4;
|
|
|
|
static constexpr int kFloatConstantCount = 4;
|
|
|
|
static constexpr int kDoubleConstantCount = 4;
|
2017-10-11 10:22:40 +00:00
|
|
|
|
|
|
|
TestEnvironment()
|
2018-11-16 13:08:55 +00:00
|
|
|
: blocks_(1, NewBlock(main_zone(), RpoNumber::FromInt(0)), main_zone()),
|
2019-02-12 09:38:11 +00:00
|
|
|
instructions_(main_isolate(), main_zone(), &blocks_),
|
2017-08-30 12:09:00 +00:00
|
|
|
rng_(CcTest::random_number_generator()),
|
2017-10-11 10:22:40 +00:00
|
|
|
supported_reps_({MachineRepresentation::kTagged,
|
|
|
|
MachineRepresentation::kFloat32,
|
|
|
|
MachineRepresentation::kFloat64}) {
|
2018-04-05 16:25:41 +00:00
|
|
|
stack_slot_count_ =
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
kTaggedSlotCount + kFloat32SlotCount + kFloat64SlotCount;
|
|
|
|
if (TestSimd128Moves()) {
|
2018-04-05 16:25:41 +00:00
|
|
|
stack_slot_count_ += kSimd128SlotCount;
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
supported_reps_.push_back(MachineRepresentation::kSimd128);
|
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
// The "teardown" and "test" functions share the same descriptor with the
|
|
|
|
// following signature:
|
|
|
|
// ~~~
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// FixedArray f(CodeObject* teardown, FixedArray preallocated_result,
|
2017-10-11 10:22:40 +00:00
|
|
|
// // Tagged registers.
|
2018-12-25 00:19:47 +00:00
|
|
|
// Object, Object, ...,
|
2017-10-11 10:22:40 +00:00
|
|
|
// // FP registers.
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// Float32, Float64, Simd128, ...,
|
2017-10-11 10:22:40 +00:00
|
|
|
// // Mixed stack slots.
|
2018-12-25 00:19:47 +00:00
|
|
|
// Float64, Object, Float32, Simd128, ...);
|
2017-10-11 10:22:40 +00:00
|
|
|
// ~~~
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
LocationSignature::Builder test_signature(
|
|
|
|
main_zone(), 1,
|
2018-04-05 16:25:41 +00:00
|
|
|
2 + kGeneralRegisterCount + kDoubleRegisterCount + stack_slot_count_);
|
2017-10-11 10:22:40 +00:00
|
|
|
|
|
|
|
// The first parameter will be the code object of the "teardown"
|
|
|
|
// function. This way, the "test" function can tail-call to it.
|
|
|
|
test_signature.AddParam(LinkageLocation::ForRegister(
|
|
|
|
kReturnRegister0.code(), MachineType::AnyTagged()));
|
|
|
|
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// The second parameter will be a pre-allocated FixedArray that the
|
|
|
|
// "teardown" function will fill with result and then return. We place this
|
|
|
|
// parameter on the first stack argument slot which is always -1. And
|
|
|
|
// therefore slots to perform moves on start at -2.
|
|
|
|
test_signature.AddParam(
|
|
|
|
LinkageLocation::ForCallerFrameSlot(-1, MachineType::AnyTagged()));
|
|
|
|
int slot_parameter_n = -2;
|
2018-04-05 16:25:41 +00:00
|
|
|
const int kTotalStackParameterCount = stack_slot_count_ + 1;
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
// Initialise registers.
|
|
|
|
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// Make sure that the target has enough general purpose registers to
|
|
|
|
// generate a call to a CodeObject using this descriptor. We have reserved
|
|
|
|
// kReturnRegister0 as the first parameter, and the call will need a
|
|
|
|
// register to hold the CodeObject address. So the maximum number of
|
|
|
|
// registers left to test with is the number of available registers minus 2.
|
2018-10-02 14:24:19 +00:00
|
|
|
DCHECK_LE(kGeneralRegisterCount,
|
|
|
|
GetRegConfig()->num_allocatable_general_registers() - 2);
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
|
2018-10-02 14:24:19 +00:00
|
|
|
int32_t general_mask = GetRegConfig()->allocatable_general_codes_mask();
|
2017-10-11 10:22:40 +00:00
|
|
|
// kReturnRegister0 is used to hold the "teardown" code object, do not
|
|
|
|
// generate moves using it.
|
|
|
|
std::unique_ptr<const RegisterConfiguration> registers(
|
|
|
|
RegisterConfiguration::RestrictGeneralRegisters(
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
general_mask & ~kReturnRegister0.bit()));
|
2017-10-11 10:22:40 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < kGeneralRegisterCount; i++) {
|
|
|
|
int code = registers->GetAllocatableGeneralCode(i);
|
|
|
|
AddRegister(&test_signature, MachineRepresentation::kTagged, code);
|
|
|
|
}
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
// We assume that Double, Float and Simd128 registers alias, depending on
|
|
|
|
// kSimpleFPAliasing. For this reason, we allocate a Float, Double and
|
|
|
|
// Simd128 together, hence the reason why `kDoubleRegisterCount` should be a
|
|
|
|
// multiple of 3 and 2 in case Simd128 is not supported.
|
|
|
|
static_assert(
|
|
|
|
((kDoubleRegisterCount % 2) == 0) && ((kDoubleRegisterCount % 3) == 0),
|
|
|
|
"kDoubleRegisterCount should be a multiple of two and three.");
|
2017-10-11 10:22:40 +00:00
|
|
|
for (int i = 0; i < kDoubleRegisterCount; i += 2) {
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
if (kSimpleFPAliasing) {
|
|
|
|
// Allocate three registers at once if kSimd128 is supported, else
|
|
|
|
// allocate in pairs.
|
|
|
|
AddRegister(&test_signature, MachineRepresentation::kFloat32,
|
|
|
|
registers->GetAllocatableFloatCode(i));
|
|
|
|
AddRegister(&test_signature, MachineRepresentation::kFloat64,
|
|
|
|
registers->GetAllocatableDoubleCode(i + 1));
|
|
|
|
if (TestSimd128Moves()) {
|
|
|
|
AddRegister(&test_signature, MachineRepresentation::kSimd128,
|
|
|
|
registers->GetAllocatableSimd128Code(i + 2));
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Make sure we do not allocate FP registers which alias. To do this, we
|
|
|
|
// allocate three 128-bit registers and then convert two of them to a
|
|
|
|
// float and a double. With this aliasing scheme, a Simd128 register
|
|
|
|
// aliases two Double registers and four Float registers, so we need to
|
|
|
|
// scale indexes accordingly:
|
|
|
|
//
|
|
|
|
// Simd128 register: q0, q1, q2, q3, q4, q5
|
|
|
|
// | | | |
|
|
|
|
// V V V V
|
|
|
|
// Aliases: s0, d2, q2, s12, d8, q5
|
|
|
|
//
|
|
|
|
// This isn't space efficient at all but suits our need.
|
|
|
|
static_assert(
|
|
|
|
kDoubleRegisterCount < 8,
|
|
|
|
"Arm has a q8 and a d16 register but no overlapping s32 register.");
|
|
|
|
int first_simd128 = registers->GetAllocatableSimd128Code(i);
|
|
|
|
int second_simd128 = registers->GetAllocatableSimd128Code(i + 1);
|
|
|
|
AddRegister(&test_signature, MachineRepresentation::kFloat32,
|
|
|
|
first_simd128 * 4);
|
|
|
|
AddRegister(&test_signature, MachineRepresentation::kFloat64,
|
|
|
|
second_simd128 * 2);
|
|
|
|
if (TestSimd128Moves()) {
|
|
|
|
int third_simd128 = registers->GetAllocatableSimd128Code(i + 2);
|
|
|
|
AddRegister(&test_signature, MachineRepresentation::kSimd128,
|
|
|
|
third_simd128);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
|
|
|
|
// Initialise stack slots.
|
|
|
|
|
|
|
|
std::map<MachineRepresentation, int> slots = {
|
|
|
|
{MachineRepresentation::kTagged, kTaggedSlotCount},
|
|
|
|
{MachineRepresentation::kFloat32, kFloat32SlotCount},
|
|
|
|
{MachineRepresentation::kFloat64, kFloat64SlotCount}};
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
if (TestSimd128Moves()) {
|
|
|
|
slots.emplace(MachineRepresentation::kSimd128, kSimd128SlotCount);
|
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
|
2017-08-30 12:09:00 +00:00
|
|
|
// Allocate new slots until we run out of them.
|
|
|
|
while (std::any_of(slots.cbegin(), slots.cend(),
|
|
|
|
[](const std::pair<MachineRepresentation, int>& entry) {
|
|
|
|
// True if there are slots left to allocate for this
|
|
|
|
// representation.
|
|
|
|
return entry.second > 0;
|
|
|
|
})) {
|
|
|
|
// Pick a random MachineRepresentation from supported_reps_.
|
|
|
|
MachineRepresentation rep = CreateRandomMachineRepresentation();
|
|
|
|
auto entry = slots.find(rep);
|
|
|
|
DCHECK(entry != slots.end());
|
|
|
|
// We may have picked a representation for which all slots have already
|
|
|
|
// been allocated.
|
|
|
|
if (entry->second > 0) {
|
|
|
|
// Keep a map of (MachineRepresentation . std::vector<int>) with
|
|
|
|
// allocated slots to pick from for each representation.
|
2017-10-11 10:22:40 +00:00
|
|
|
int slot = slot_parameter_n;
|
2019-02-14 13:01:52 +00:00
|
|
|
slot_parameter_n -= (GetSlotSizeInBytes(rep) / kSystemPointerSize);
|
2017-10-11 10:22:40 +00:00
|
|
|
AddStackSlot(&test_signature, rep, slot);
|
2017-08-30 12:09:00 +00:00
|
|
|
entry->second--;
|
|
|
|
}
|
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
|
|
|
|
// Initialise random constants.
|
|
|
|
|
|
|
|
// While constants do not know about Smis, we need to be able to
|
|
|
|
// differentiate between a pointer to a HeapNumber and a integer. For this
|
|
|
|
// reason, we make sure all integers are Smis, including constants.
|
|
|
|
for (int i = 0; i < kSmiConstantCount; i++) {
|
2018-11-03 00:13:22 +00:00
|
|
|
intptr_t smi_value = static_cast<intptr_t>(
|
|
|
|
Smi::FromInt(rng_->NextInt(Smi::kMaxValue)).ptr());
|
2019-02-14 13:01:52 +00:00
|
|
|
Constant constant = kSystemPointerSize == 8
|
2017-10-11 10:22:40 +00:00
|
|
|
? Constant(static_cast<int64_t>(smi_value))
|
|
|
|
: Constant(static_cast<int32_t>(smi_value));
|
|
|
|
AddConstant(MachineRepresentation::kTagged, AllocateConstant(constant));
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
// Float and Double constants can be moved to both Tagged and FP registers
|
|
|
|
// or slots. Register them as compatible with both FP and Tagged
|
|
|
|
// destinations.
|
|
|
|
for (int i = 0; i < kFloatConstantCount; i++) {
|
|
|
|
int virtual_register =
|
|
|
|
AllocateConstant(Constant(DoubleToFloat32(rng_->NextDouble())));
|
|
|
|
AddConstant(MachineRepresentation::kTagged, virtual_register);
|
|
|
|
AddConstant(MachineRepresentation::kFloat32, virtual_register);
|
|
|
|
}
|
|
|
|
for (int i = 0; i < kDoubleConstantCount; i++) {
|
|
|
|
int virtual_register = AllocateConstant(Constant(rng_->NextDouble()));
|
|
|
|
AddConstant(MachineRepresentation::kTagged, virtual_register);
|
|
|
|
AddConstant(MachineRepresentation::kFloat64, virtual_register);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The "teardown" function returns a FixedArray with the resulting state.
|
|
|
|
test_signature.AddReturn(LinkageLocation::ForRegister(
|
|
|
|
kReturnRegister0.code(), MachineType::AnyTagged()));
|
|
|
|
|
|
|
|
test_descriptor_ = new (main_zone())
|
|
|
|
CallDescriptor(CallDescriptor::kCallCodeObject, // kind
|
|
|
|
MachineType::AnyTagged(), // target MachineType
|
|
|
|
LinkageLocation::ForAnyRegister(
|
|
|
|
MachineType::AnyTagged()), // target location
|
|
|
|
test_signature.Build(), // location_sig
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
kTotalStackParameterCount, // stack_parameter_count
|
2017-10-11 10:22:40 +00:00
|
|
|
Operator::kNoProperties, // properties
|
|
|
|
kNoCalleeSaved, // callee-saved registers
|
|
|
|
kNoCalleeSaved, // callee-saved fp
|
|
|
|
CallDescriptor::kNoFlags); // flags
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int AllocateConstant(Constant constant) {
|
2019-02-12 09:38:11 +00:00
|
|
|
int virtual_register = instructions_.NextVirtualRegister();
|
|
|
|
instructions_.AddConstant(virtual_register, constant);
|
2017-08-30 12:09:00 +00:00
|
|
|
return virtual_register;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a constant referenced by `virtual_register` as compatible with
|
|
|
|
// `rep`.
|
2017-10-11 10:22:40 +00:00
|
|
|
void AddConstant(MachineRepresentation rep, int virtual_register) {
|
|
|
|
auto entry = allocated_constants_.find(rep);
|
|
|
|
if (entry == allocated_constants_.end()) {
|
2017-10-17 17:28:35 +00:00
|
|
|
allocated_constants_.emplace(
|
|
|
|
rep, std::vector<ConstantOperand>{ConstantOperand(virtual_register)});
|
2017-08-30 12:09:00 +00:00
|
|
|
} else {
|
2017-10-17 17:28:35 +00:00
|
|
|
entry->second.emplace_back(virtual_register);
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
// Register a new register or stack slot as compatible with `rep`. As opposed
|
|
|
|
// to constants, registers and stack slots are written to on `setup` and read
|
|
|
|
// from on `teardown`. Therefore they are part of the environment's layout,
|
|
|
|
// and are parameters of the `test` function.
|
|
|
|
|
|
|
|
void AddRegister(LocationSignature::Builder* test_signature,
|
|
|
|
MachineRepresentation rep, int code) {
|
2017-10-17 17:28:35 +00:00
|
|
|
AllocatedOperand operand(AllocatedOperand::REGISTER, rep, code);
|
|
|
|
layout_.push_back(operand);
|
2017-10-11 10:22:40 +00:00
|
|
|
test_signature->AddParam(LinkageLocation::ForRegister(
|
|
|
|
code, MachineType::TypeForRepresentation(rep)));
|
|
|
|
auto entry = allocated_registers_.find(rep);
|
|
|
|
if (entry == allocated_registers_.end()) {
|
2017-10-17 17:28:35 +00:00
|
|
|
allocated_registers_.emplace(rep, std::vector<AllocatedOperand>{operand});
|
2017-10-11 10:22:40 +00:00
|
|
|
} else {
|
2017-10-17 17:28:35 +00:00
|
|
|
entry->second.push_back(operand);
|
2017-10-11 10:22:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AddStackSlot(LocationSignature::Builder* test_signature,
|
|
|
|
MachineRepresentation rep, int slot) {
|
2017-10-17 17:28:35 +00:00
|
|
|
AllocatedOperand operand(AllocatedOperand::STACK_SLOT, rep, slot);
|
|
|
|
layout_.push_back(operand);
|
2017-10-11 10:22:40 +00:00
|
|
|
test_signature->AddParam(LinkageLocation::ForCallerFrameSlot(
|
|
|
|
slot, MachineType::TypeForRepresentation(rep)));
|
2017-08-30 12:09:00 +00:00
|
|
|
auto entry = allocated_slots_.find(rep);
|
|
|
|
if (entry == allocated_slots_.end()) {
|
2017-10-17 17:28:35 +00:00
|
|
|
allocated_slots_.emplace(rep, std::vector<AllocatedOperand>{operand});
|
2017-08-30 12:09:00 +00:00
|
|
|
} else {
|
2017-10-17 17:28:35 +00:00
|
|
|
entry->second.push_back(operand);
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
2017-07-13 09:55:16 +00:00
|
|
|
}
|
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
// Generate a random initial state to test moves against. A "state" is a
|
|
|
|
// packed FixedArray with Smis and HeapNumbers, according to the layout of the
|
|
|
|
// environment.
|
|
|
|
Handle<FixedArray> GenerateInitialState() {
|
|
|
|
Handle<FixedArray> state = main_isolate()->factory()->NewFixedArray(
|
|
|
|
static_cast<int>(layout_.size()));
|
|
|
|
for (int i = 0; i < state->length(); i++) {
|
2017-10-17 17:28:35 +00:00
|
|
|
switch (layout_[i].representation()) {
|
2017-10-11 10:22:40 +00:00
|
|
|
case MachineRepresentation::kTagged:
|
|
|
|
state->set(i, Smi::FromInt(rng_->NextInt(Smi::kMaxValue)));
|
|
|
|
break;
|
2018-09-07 10:21:41 +00:00
|
|
|
case MachineRepresentation::kFloat32: {
|
2017-10-11 10:22:40 +00:00
|
|
|
// HeapNumbers are Float64 values. However, we will convert it to a
|
|
|
|
// Float32 and back inside `setup` and `teardown`. Make sure the value
|
|
|
|
// we pick fits in a Float32.
|
2018-09-07 10:21:41 +00:00
|
|
|
Handle<HeapNumber> num = main_isolate()->factory()->NewHeapNumber(
|
|
|
|
static_cast<double>(DoubleToFloat32(rng_->NextDouble())));
|
|
|
|
state->set(i, *num);
|
2017-10-11 10:22:40 +00:00
|
|
|
break;
|
2018-09-07 10:21:41 +00:00
|
|
|
}
|
|
|
|
case MachineRepresentation::kFloat64: {
|
|
|
|
Handle<HeapNumber> num =
|
|
|
|
main_isolate()->factory()->NewHeapNumber(rng_->NextDouble());
|
|
|
|
state->set(i, *num);
|
2017-10-11 10:22:40 +00:00
|
|
|
break;
|
2018-09-07 10:21:41 +00:00
|
|
|
}
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
case MachineRepresentation::kSimd128: {
|
|
|
|
Handle<FixedArray> vector =
|
|
|
|
main_isolate()->factory()->NewFixedArray(4);
|
|
|
|
for (int lane = 0; lane < 4; lane++) {
|
|
|
|
vector->set(lane, Smi::FromInt(rng_->NextInt(Smi::kMaxValue)));
|
|
|
|
}
|
|
|
|
state->set(i, *vector);
|
|
|
|
break;
|
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run the code generated by a CodeGeneratorTester against `state_in` and
|
|
|
|
// return a new resulting state.
|
|
|
|
Handle<FixedArray> Run(Handle<Code> test, Handle<FixedArray> state_in) {
|
|
|
|
Handle<FixedArray> state_out = main_isolate()->factory()->NewFixedArray(
|
|
|
|
static_cast<int>(layout_.size()));
|
|
|
|
{
|
2018-06-11 16:19:00 +00:00
|
|
|
#ifdef ENABLE_SLOW_DCHECKS
|
|
|
|
// The "setup" and "teardown" functions are relatively big, and with
|
|
|
|
// runtime assertions enabled they get so big that memory during register
|
|
|
|
// allocation becomes a problem. Temporarily disable such assertions.
|
|
|
|
bool old_enable_slow_asserts = FLAG_enable_slow_asserts;
|
|
|
|
FLAG_enable_slow_asserts = false;
|
|
|
|
#endif
|
2017-10-11 10:22:40 +00:00
|
|
|
Handle<Code> setup =
|
|
|
|
BuildSetupFunction(main_isolate(), test_descriptor_, layout_);
|
2018-06-11 16:19:00 +00:00
|
|
|
#ifdef ENABLE_SLOW_DCHECKS
|
|
|
|
FLAG_enable_slow_asserts = old_enable_slow_asserts;
|
|
|
|
#endif
|
2017-10-11 10:22:40 +00:00
|
|
|
// FunctionTester maintains its own HandleScope which means that its
|
|
|
|
// return value will be freed along with it. Copy the result into
|
|
|
|
// state_out.
|
|
|
|
FunctionTester ft(setup, 2);
|
|
|
|
Handle<FixedArray> result = ft.CallChecked<FixedArray>(test, state_in);
|
|
|
|
CHECK_EQ(result->length(), state_in->length());
|
|
|
|
result->CopyTo(0, *state_out, 0, result->length());
|
|
|
|
}
|
|
|
|
return state_out;
|
|
|
|
}
|
|
|
|
|
2017-10-17 17:28:35 +00:00
|
|
|
// For a given operand representing either a register or a stack slot, return
|
|
|
|
// what position it should live in inside a FixedArray state.
|
|
|
|
int OperandToStatePosition(const AllocatedOperand& operand) const {
|
|
|
|
// Search `layout_` for `operand`.
|
|
|
|
auto it = std::find_if(layout_.cbegin(), layout_.cend(),
|
|
|
|
[operand](const AllocatedOperand& this_operand) {
|
|
|
|
return this_operand.Equals(operand);
|
|
|
|
});
|
|
|
|
DCHECK_NE(it, layout_.cend());
|
|
|
|
return static_cast<int>(std::distance(layout_.cbegin(), it));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform the given list of moves on `state_in` and return a newly allocated
|
|
|
|
// state with the results.
|
|
|
|
Handle<FixedArray> SimulateMoves(ParallelMove* moves,
|
|
|
|
Handle<FixedArray> state_in) {
|
|
|
|
Handle<FixedArray> state_out = main_isolate()->factory()->NewFixedArray(
|
|
|
|
static_cast<int>(layout_.size()));
|
|
|
|
// We do not want to modify `state_in` in place so perform the moves on a
|
|
|
|
// copy.
|
|
|
|
state_in->CopyTo(0, *state_out, 0, state_in->length());
|
|
|
|
for (auto move : *moves) {
|
|
|
|
int to_index =
|
|
|
|
OperandToStatePosition(AllocatedOperand::cast(move->destination()));
|
|
|
|
InstructionOperand from = move->source();
|
|
|
|
if (from.IsConstant()) {
|
2019-02-12 09:38:11 +00:00
|
|
|
Constant constant = instructions_.GetConstant(
|
|
|
|
ConstantOperand::cast(from).virtual_register());
|
2017-10-17 17:28:35 +00:00
|
|
|
Handle<Object> constant_value;
|
|
|
|
switch (constant.type()) {
|
|
|
|
case Constant::kInt32:
|
|
|
|
constant_value =
|
2018-11-03 00:13:22 +00:00
|
|
|
Handle<Smi>(Smi(static_cast<Address>(
|
|
|
|
static_cast<intptr_t>(constant.ToInt32()))),
|
2017-10-17 17:28:35 +00:00
|
|
|
main_isolate());
|
|
|
|
break;
|
|
|
|
case Constant::kInt64:
|
2018-11-03 00:13:22 +00:00
|
|
|
constant_value = Handle<Smi>(
|
|
|
|
Smi(static_cast<Address>(constant.ToInt64())), main_isolate());
|
2017-10-17 17:28:35 +00:00
|
|
|
break;
|
|
|
|
case Constant::kFloat32:
|
|
|
|
constant_value = main_isolate()->factory()->NewHeapNumber(
|
|
|
|
static_cast<double>(constant.ToFloat32()));
|
|
|
|
break;
|
|
|
|
case Constant::kFloat64:
|
|
|
|
constant_value = main_isolate()->factory()->NewHeapNumber(
|
|
|
|
constant.ToFloat64().value());
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
state_out->set(to_index, *constant_value);
|
|
|
|
} else {
|
|
|
|
int from_index = OperandToStatePosition(AllocatedOperand::cast(from));
|
2019-05-21 17:11:13 +00:00
|
|
|
state_out->set(to_index, state_out->get(from_index));
|
2017-10-17 17:28:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return state_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform the given list of swaps on `state_in` and return a newly allocated
|
|
|
|
// state with the results.
|
|
|
|
Handle<FixedArray> SimulateSwaps(ParallelMove* swaps,
|
|
|
|
Handle<FixedArray> state_in) {
|
|
|
|
Handle<FixedArray> state_out = main_isolate()->factory()->NewFixedArray(
|
|
|
|
static_cast<int>(layout_.size()));
|
|
|
|
// We do not want to modify `state_in` in place so perform the swaps on a
|
|
|
|
// copy.
|
|
|
|
state_in->CopyTo(0, *state_out, 0, state_in->length());
|
|
|
|
for (auto swap : *swaps) {
|
|
|
|
int lhs_index =
|
|
|
|
OperandToStatePosition(AllocatedOperand::cast(swap->destination()));
|
|
|
|
int rhs_index =
|
|
|
|
OperandToStatePosition(AllocatedOperand::cast(swap->source()));
|
2019-05-21 17:11:13 +00:00
|
|
|
Handle<Object> lhs{state_out->get(lhs_index), main_isolate()};
|
|
|
|
Handle<Object> rhs{state_out->get(rhs_index), main_isolate()};
|
2017-10-17 17:28:35 +00:00
|
|
|
state_out->set(lhs_index, *rhs);
|
|
|
|
state_out->set(rhs_index, *lhs);
|
|
|
|
}
|
|
|
|
return state_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compare the given state with a reference.
|
|
|
|
void CheckState(Handle<FixedArray> actual, Handle<FixedArray> expected) {
|
|
|
|
for (int i = 0; i < static_cast<int>(layout_.size()); i++) {
|
2019-05-21 17:11:13 +00:00
|
|
|
Handle<Object> actual_value{actual->get(i), main_isolate()};
|
|
|
|
Handle<Object> expected_value{expected->get(i), main_isolate()};
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
if (!CompareValues(actual_value, expected_value,
|
|
|
|
layout_[i].representation())) {
|
2017-10-17 17:28:35 +00:00
|
|
|
std::ostringstream expected_str;
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
PrintStateValue(expected_str, main_isolate(), expected_value,
|
|
|
|
layout_[i]);
|
2017-10-17 17:28:35 +00:00
|
|
|
std::ostringstream actual_str;
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
PrintStateValue(actual_str, main_isolate(), actual_value, layout_[i]);
|
2019-05-10 18:55:22 +00:00
|
|
|
FATAL("Expected: '%s' but got '%s'", expected_str.str().c_str(),
|
|
|
|
actual_str.str().c_str());
|
2017-10-11 10:22:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-07-13 09:55:16 +00:00
|
|
|
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
bool CompareValues(Handle<Object> actual, Handle<Object> expected,
|
|
|
|
MachineRepresentation rep) {
|
|
|
|
switch (rep) {
|
|
|
|
case MachineRepresentation::kTagged:
|
|
|
|
case MachineRepresentation::kFloat32:
|
|
|
|
case MachineRepresentation::kFloat64:
|
|
|
|
return actual->StrictEquals(*expected);
|
|
|
|
case MachineRepresentation::kSimd128:
|
|
|
|
for (int lane = 0; lane < 4; lane++) {
|
2019-05-21 17:11:13 +00:00
|
|
|
int actual_lane =
|
2019-05-23 07:47:44 +00:00
|
|
|
Smi::cast(FixedArray::cast(*actual).get(lane)).value();
|
2019-05-21 17:11:13 +00:00
|
|
|
int expected_lane =
|
2019-05-23 07:47:44 +00:00
|
|
|
Smi::cast(FixedArray::cast(*expected).get(lane)).value();
|
2019-05-21 17:11:13 +00:00
|
|
|
if (actual_lane != expected_lane) {
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-30 12:09:00 +00:00
|
|
|
enum OperandConstraint {
|
|
|
|
kNone,
|
|
|
|
// Restrict operands to non-constants. This is useful when generating a
|
|
|
|
// destination.
|
|
|
|
kCannotBeConstant
|
|
|
|
};
|
|
|
|
|
|
|
|
// Generate parallel moves at random. Note that they may not be compatible
|
|
|
|
// between each other as this doesn't matter to the code generator.
|
|
|
|
ParallelMove* GenerateRandomMoves(int size) {
|
|
|
|
ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone());
|
|
|
|
|
|
|
|
for (int i = 0; i < size;) {
|
|
|
|
MachineRepresentation rep = CreateRandomMachineRepresentation();
|
|
|
|
MoveOperands mo(CreateRandomOperand(kNone, rep),
|
|
|
|
CreateRandomOperand(kCannotBeConstant, rep));
|
|
|
|
// It isn't valid to call `AssembleMove` and `AssembleSwap` with redundant
|
|
|
|
// moves.
|
|
|
|
if (mo.IsRedundant()) continue;
|
|
|
|
parallel_move->AddMove(mo.source(), mo.destination());
|
|
|
|
// Iterate only when a move was created.
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return parallel_move;
|
|
|
|
}
|
|
|
|
|
|
|
|
ParallelMove* GenerateRandomSwaps(int size) {
|
|
|
|
ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone());
|
|
|
|
|
|
|
|
for (int i = 0; i < size;) {
|
|
|
|
MachineRepresentation rep = CreateRandomMachineRepresentation();
|
|
|
|
InstructionOperand lhs = CreateRandomOperand(kCannotBeConstant, rep);
|
|
|
|
InstructionOperand rhs = CreateRandomOperand(kCannotBeConstant, rep);
|
|
|
|
MoveOperands mo(lhs, rhs);
|
|
|
|
// It isn't valid to call `AssembleMove` and `AssembleSwap` with redundant
|
|
|
|
// moves.
|
|
|
|
if (mo.IsRedundant()) continue;
|
|
|
|
// Canonicalize the swap: the register operand has to be the left hand
|
|
|
|
// side.
|
|
|
|
if (lhs.IsStackSlot() || lhs.IsFPStackSlot()) {
|
|
|
|
std::swap(lhs, rhs);
|
|
|
|
}
|
|
|
|
parallel_move->AddMove(lhs, rhs);
|
|
|
|
// Iterate only when a swap was created.
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return parallel_move;
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineRepresentation CreateRandomMachineRepresentation() {
|
|
|
|
int index = rng_->NextInt(static_cast<int>(supported_reps_.size()));
|
|
|
|
return supported_reps_[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
InstructionOperand CreateRandomOperand(OperandConstraint constraint,
|
|
|
|
MachineRepresentation rep) {
|
|
|
|
// Only generate a Constant if the operand is a source and we have a
|
|
|
|
// constant with a compatible representation in stock.
|
2017-10-11 10:22:40 +00:00
|
|
|
bool generate_constant =
|
|
|
|
(constraint != kCannotBeConstant) &&
|
|
|
|
(allocated_constants_.find(rep) != allocated_constants_.end());
|
2017-08-30 12:09:00 +00:00
|
|
|
switch (rng_->NextInt(generate_constant ? 3 : 2)) {
|
|
|
|
case 0:
|
|
|
|
return CreateRandomStackSlotOperand(rep);
|
|
|
|
case 1:
|
|
|
|
return CreateRandomRegisterOperand(rep);
|
|
|
|
case 2:
|
|
|
|
return CreateRandomConstant(rep);
|
|
|
|
}
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2017-10-17 17:28:35 +00:00
|
|
|
AllocatedOperand CreateRandomRegisterOperand(MachineRepresentation rep) {
|
2017-10-11 10:22:40 +00:00
|
|
|
int index =
|
|
|
|
rng_->NextInt(static_cast<int>(allocated_registers_[rep].size()));
|
2017-10-17 17:28:35 +00:00
|
|
|
return allocated_registers_[rep][index];
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
|
|
|
|
2017-10-17 17:28:35 +00:00
|
|
|
AllocatedOperand CreateRandomStackSlotOperand(MachineRepresentation rep) {
|
2017-08-30 12:09:00 +00:00
|
|
|
int index = rng_->NextInt(static_cast<int>(allocated_slots_[rep].size()));
|
2017-10-17 17:28:35 +00:00
|
|
|
return allocated_slots_[rep][index];
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
|
|
|
|
2017-10-17 17:28:35 +00:00
|
|
|
ConstantOperand CreateRandomConstant(MachineRepresentation rep) {
|
2017-10-11 10:22:40 +00:00
|
|
|
int index =
|
|
|
|
rng_->NextInt(static_cast<int>(allocated_constants_[rep].size()));
|
2017-10-17 17:28:35 +00:00
|
|
|
return allocated_constants_[rep][index];
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
|
|
|
|
2018-11-16 13:08:55 +00:00
|
|
|
static InstructionBlock* NewBlock(Zone* zone, RpoNumber rpo) {
|
|
|
|
return new (zone) InstructionBlock(zone, rpo, RpoNumber::Invalid(),
|
|
|
|
RpoNumber::Invalid(), false, false);
|
|
|
|
}
|
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
v8::base::RandomNumberGenerator* rng() const { return rng_; }
|
2019-02-12 09:38:11 +00:00
|
|
|
InstructionSequence* instructions() { return &instructions_; }
|
2017-10-11 10:22:40 +00:00
|
|
|
CallDescriptor* test_descriptor() { return test_descriptor_; }
|
2018-04-05 16:25:41 +00:00
|
|
|
int stack_slot_count() const { return stack_slot_count_; }
|
2017-10-11 10:22:40 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
ZoneVector<InstructionBlock*> blocks_;
|
2019-02-12 09:38:11 +00:00
|
|
|
InstructionSequence instructions_;
|
2017-10-11 10:22:40 +00:00
|
|
|
v8::base::RandomNumberGenerator* rng_;
|
2017-10-17 17:28:35 +00:00
|
|
|
// The layout describes the type of each element in the environment, in order.
|
|
|
|
std::vector<AllocatedOperand> layout_;
|
2017-10-11 10:22:40 +00:00
|
|
|
CallDescriptor* test_descriptor_;
|
|
|
|
// Allocated constants, registers and stack slots that we can generate moves
|
|
|
|
// with. Each per compatible representation.
|
|
|
|
std::vector<MachineRepresentation> supported_reps_;
|
2017-10-17 17:28:35 +00:00
|
|
|
std::map<MachineRepresentation, std::vector<ConstantOperand>>
|
|
|
|
allocated_constants_;
|
|
|
|
std::map<MachineRepresentation, std::vector<AllocatedOperand>>
|
|
|
|
allocated_registers_;
|
|
|
|
std::map<MachineRepresentation, std::vector<AllocatedOperand>>
|
|
|
|
allocated_slots_;
|
2018-04-05 16:25:41 +00:00
|
|
|
int stack_slot_count_;
|
2017-10-11 10:22:40 +00:00
|
|
|
};
|
|
|
|
|
2017-10-23 06:49:35 +00:00
|
|
|
// static
|
|
|
|
constexpr int TestEnvironment::kGeneralRegisterCount;
|
|
|
|
constexpr int TestEnvironment::kDoubleRegisterCount;
|
|
|
|
constexpr int TestEnvironment::kTaggedSlotCount;
|
|
|
|
constexpr int TestEnvironment::kFloat32SlotCount;
|
|
|
|
constexpr int TestEnvironment::kFloat64SlotCount;
|
[cctest] Support testing Simd128 moves and swaps
Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.
For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.
As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.
Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.
Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843.
Bug: v8:6848
Change-Id: I8787d6339cdbfcd9356c5e8995925f0b45c562fa
Reviewed-on: https://chromium-review.googlesource.com/728599
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50326}
2018-01-02 11:27:15 +00:00
|
|
|
constexpr int TestEnvironment::kSimd128SlotCount;
|
2017-10-23 06:49:35 +00:00
|
|
|
constexpr int TestEnvironment::kSmiConstantCount;
|
|
|
|
constexpr int TestEnvironment::kFloatConstantCount;
|
|
|
|
constexpr int TestEnvironment::kDoubleConstantCount;
|
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
// Wrapper around the CodeGenerator. Code generated by this can only be called
|
|
|
|
// using the given `TestEnvironment`.
|
|
|
|
class CodeGeneratorTester {
|
|
|
|
public:
|
2018-04-05 16:25:41 +00:00
|
|
|
explicit CodeGeneratorTester(TestEnvironment* environment,
|
|
|
|
int extra_stack_space = 0)
|
2017-10-11 10:22:40 +00:00
|
|
|
: zone_(environment->main_zone()),
|
2017-11-15 14:36:57 +00:00
|
|
|
info_(ArrayVector("test"), environment->main_zone(), Code::STUB),
|
2017-10-11 10:22:40 +00:00
|
|
|
linkage_(environment->test_descriptor()),
|
2019-06-27 12:46:03 +00:00
|
|
|
frame_(environment->test_descriptor()->CalculateFixedFrameSize(
|
|
|
|
Code::STUB)) {
|
2018-04-05 16:25:41 +00:00
|
|
|
// Pick half of the stack parameters at random and move them into spill
|
2018-09-07 10:21:41 +00:00
|
|
|
// slots, separated by `extra_stack_space` bytes.
|
2018-04-05 16:25:41 +00:00
|
|
|
// When testing a move with stack slots using CheckAssembleMove or
|
|
|
|
// CheckAssembleSwap, we'll transparently make use of local spill slots
|
|
|
|
// instead of stack parameters for those that were picked. This allows us to
|
|
|
|
// test negative, positive, far and near ranges.
|
|
|
|
for (int i = 0; i < (environment->stack_slot_count() / 2);) {
|
|
|
|
MachineRepresentation rep =
|
|
|
|
environment->CreateRandomMachineRepresentation();
|
|
|
|
LocationOperand old_slot =
|
|
|
|
LocationOperand::cast(environment->CreateRandomStackSlotOperand(rep));
|
|
|
|
// Do not pick the same slot twice.
|
|
|
|
if (GetSpillSlot(&old_slot) != spill_slots_.end()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
LocationOperand new_slot =
|
|
|
|
AllocatedOperand(LocationOperand::STACK_SLOT, rep,
|
|
|
|
frame_.AllocateSpillSlot(GetSlotSizeInBytes(rep)));
|
|
|
|
// Artificially create space on the stack by allocating a new slot.
|
|
|
|
if (extra_stack_space > 0) {
|
|
|
|
frame_.AllocateSpillSlot(extra_stack_space);
|
|
|
|
}
|
|
|
|
spill_slots_.emplace_back(old_slot, new_slot);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
generator_ = new CodeGenerator(
|
2019-02-12 09:38:11 +00:00
|
|
|
environment->main_zone(), &frame_, &linkage_,
|
|
|
|
environment->instructions(), &info_, environment->main_isolate(),
|
|
|
|
base::Optional<OsrHelper>(), kNoSourcePosition, nullptr,
|
|
|
|
PoisoningMitigationLevel::kDontPoison,
|
2018-07-09 07:51:35 +00:00
|
|
|
AssemblerOptions::Default(environment->main_isolate()),
|
|
|
|
Builtins::kNoBuiltinId);
|
2018-04-05 16:25:41 +00:00
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
// Force a frame to be created.
|
2018-04-05 16:25:41 +00:00
|
|
|
generator_->frame_access_state()->MarkHasFrame(true);
|
|
|
|
generator_->AssembleConstructFrame();
|
2017-10-11 10:22:40 +00:00
|
|
|
// TODO(all): Generate a stack check here so that we fail gracefully if the
|
|
|
|
// frame is too big.
|
2018-04-05 16:25:41 +00:00
|
|
|
|
|
|
|
// Move chosen stack parameters into spill slots.
|
|
|
|
for (auto move : spill_slots_) {
|
|
|
|
generator_->AssembleMove(&move.first, &move.second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~CodeGeneratorTester() { delete generator_; }
|
|
|
|
|
|
|
|
std::vector<std::pair<LocationOperand, LocationOperand>>::iterator
|
|
|
|
GetSpillSlot(InstructionOperand* op) {
|
|
|
|
if (op->IsAnyStackSlot()) {
|
|
|
|
LocationOperand slot = LocationOperand::cast(*op);
|
|
|
|
return std::find_if(
|
|
|
|
spill_slots_.begin(), spill_slots_.end(),
|
|
|
|
[slot](
|
|
|
|
const std::pair<LocationOperand, LocationOperand>& moved_pair) {
|
|
|
|
return moved_pair.first.index() == slot.index();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return spill_slots_.end();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the operand corresponds to a spill slot, return it. Else just pass it
|
|
|
|
// through.
|
|
|
|
InstructionOperand* MaybeTranslateSlot(InstructionOperand* op) {
|
|
|
|
auto it = GetSpillSlot(op);
|
|
|
|
if (it != spill_slots_.end()) {
|
|
|
|
// The second element is the spill slot associated with op.
|
|
|
|
return &it->second;
|
|
|
|
} else {
|
|
|
|
return op;
|
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
}
|
|
|
|
|
2017-12-04 14:19:25 +00:00
|
|
|
Instruction* CreateTailCall(int stack_slot_delta) {
|
2017-12-15 17:01:32 +00:00
|
|
|
int optional_padding_slot = stack_slot_delta;
|
2017-12-04 14:19:25 +00:00
|
|
|
InstructionOperand callee[] = {
|
[turbofan] IA32 port of branch load poisoning.
The tricky part here is to take away one register from register
allocation for the mask. The only problem is with calls that need
an input operand to be passed in the poison register. For such calls,
we change the register constraint in the instruction selector
to pass the value in whatever place the register allocator sees fit.
During code generation, we then copy the value from that place
to the poison register. By that time, the mask is not necessary
(once we bake the mask into the target, it should be done before
this move).
For the branches, the mask update does not use cmov (unlike x64)
because cmov does not take an immediate and we do not have
a scratch register. Instead we use bit-twiddling tricks
(suggested by @tebbi). For example, here is the code for masking
register update after a bailout on non-zero:
jnz deopt_bailout ;; Bailout branch
setnz bl ;; These three instructions update the mask
add ebx, 255
sar ebx, 31
(On x64, the sequence is:
jnz deopt_bailout
mov r10, 0 ;; We have a scratch register for zero
cmovnz r9, r10 ;; Set to zero if we execute this branch
;; in branch mis-speculation
)
This CL also fixes a bug in register configuration, where we used
to wrongly restrict the array of register name.
Change-Id: I5fceff2faf8bdc527d9934afc284b749574ab69e
Bug: chromium:798964
Reviewed-on: https://chromium-review.googlesource.com/946251
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51798}
2018-03-07 06:35:45 +00:00
|
|
|
AllocatedOperand(LocationOperand::REGISTER,
|
|
|
|
MachineRepresentation::kTagged,
|
|
|
|
kReturnRegister0.code()),
|
|
|
|
ImmediateOperand(ImmediateOperand::INLINE, -1), // poison index.
|
2017-12-15 17:01:32 +00:00
|
|
|
ImmediateOperand(ImmediateOperand::INLINE, optional_padding_slot),
|
2017-12-04 14:19:25 +00:00
|
|
|
ImmediateOperand(ImmediateOperand::INLINE, stack_slot_delta)};
|
[turbofan] IA32 port of branch load poisoning.
The tricky part here is to take away one register from register
allocation for the mask. The only problem is with calls that need
an input operand to be passed in the poison register. For such calls,
we change the register constraint in the instruction selector
to pass the value in whatever place the register allocator sees fit.
During code generation, we then copy the value from that place
to the poison register. By that time, the mask is not necessary
(once we bake the mask into the target, it should be done before
this move).
For the branches, the mask update does not use cmov (unlike x64)
because cmov does not take an immediate and we do not have
a scratch register. Instead we use bit-twiddling tricks
(suggested by @tebbi). For example, here is the code for masking
register update after a bailout on non-zero:
jnz deopt_bailout ;; Bailout branch
setnz bl ;; These three instructions update the mask
add ebx, 255
sar ebx, 31
(On x64, the sequence is:
jnz deopt_bailout
mov r10, 0 ;; We have a scratch register for zero
cmovnz r9, r10 ;; Set to zero if we execute this branch
;; in branch mis-speculation
)
This CL also fixes a bug in register configuration, where we used
to wrongly restrict the array of register name.
Change-Id: I5fceff2faf8bdc527d9934afc284b749574ab69e
Bug: chromium:798964
Reviewed-on: https://chromium-review.googlesource.com/946251
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51798}
2018-03-07 06:35:45 +00:00
|
|
|
Instruction* tail_call =
|
|
|
|
Instruction::New(zone_, kArchTailCallCodeObject, 0, nullptr,
|
|
|
|
arraysize(callee), callee, 0, nullptr);
|
2017-12-04 14:19:25 +00:00
|
|
|
return tail_call;
|
|
|
|
}
|
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
enum PushTypeFlag {
|
|
|
|
kRegisterPush = CodeGenerator::kRegisterPush,
|
|
|
|
kStackSlotPush = CodeGenerator::kStackSlotPush,
|
|
|
|
kScalarPush = CodeGenerator::kScalarPush
|
|
|
|
};
|
|
|
|
|
2017-07-13 09:55:16 +00:00
|
|
|
void CheckAssembleTailCallGaps(Instruction* instr,
|
|
|
|
int first_unused_stack_slot,
|
|
|
|
CodeGeneratorTester::PushTypeFlag push_type) {
|
2018-04-05 16:25:41 +00:00
|
|
|
generator_->AssembleTailCallBeforeGap(instr, first_unused_stack_slot);
|
2017-08-02 19:24:16 +00:00
|
|
|
#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_S390) || \
|
|
|
|
defined(V8_TARGET_ARCH_PPC)
|
2017-07-13 09:55:16 +00:00
|
|
|
// Only folding register pushes is supported on ARM.
|
|
|
|
bool supported = ((push_type & CodeGenerator::kRegisterPush) == push_type);
|
|
|
|
#elif defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_IA32) || \
|
2017-08-02 19:24:16 +00:00
|
|
|
defined(V8_TARGET_ARCH_X87)
|
2017-07-13 09:55:16 +00:00
|
|
|
bool supported = ((push_type & CodeGenerator::kScalarPush) == push_type);
|
|
|
|
#else
|
|
|
|
bool supported = false;
|
|
|
|
#endif
|
|
|
|
if (supported) {
|
|
|
|
// Architectures supporting folding adjacent pushes should now have
|
|
|
|
// resolved all moves.
|
|
|
|
for (const auto& move :
|
|
|
|
*instr->parallel_moves()[Instruction::FIRST_GAP_POSITION]) {
|
|
|
|
CHECK(move->IsEliminated());
|
|
|
|
}
|
|
|
|
}
|
2018-04-05 16:25:41 +00:00
|
|
|
generator_->AssembleGaps(instr);
|
|
|
|
generator_->AssembleTailCallAfterGap(instr, first_unused_stack_slot);
|
2017-07-13 09:55:16 +00:00
|
|
|
}
|
|
|
|
|
2017-08-30 12:09:00 +00:00
|
|
|
void CheckAssembleMove(InstructionOperand* source,
|
|
|
|
InstructionOperand* destination) {
|
2018-04-05 16:25:41 +00:00
|
|
|
int start = generator_->tasm()->pc_offset();
|
|
|
|
generator_->AssembleMove(MaybeTranslateSlot(source),
|
|
|
|
MaybeTranslateSlot(destination));
|
|
|
|
CHECK(generator_->tasm()->pc_offset() > start);
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CheckAssembleSwap(InstructionOperand* source,
|
|
|
|
InstructionOperand* destination) {
|
2018-04-05 16:25:41 +00:00
|
|
|
int start = generator_->tasm()->pc_offset();
|
|
|
|
generator_->AssembleSwap(MaybeTranslateSlot(source),
|
|
|
|
MaybeTranslateSlot(destination));
|
|
|
|
CHECK(generator_->tasm()->pc_offset() > start);
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
|
|
|
|
2017-07-13 09:55:16 +00:00
|
|
|
Handle<Code> Finalize() {
|
2018-04-05 16:25:41 +00:00
|
|
|
generator_->FinishCode();
|
|
|
|
generator_->safepoints()->Emit(generator_->tasm(),
|
|
|
|
frame_.GetTotalFrameSlotCount());
|
2019-02-01 10:51:37 +00:00
|
|
|
generator_->MaybeEmitOutOfLineConstantPool();
|
|
|
|
|
2018-06-19 08:09:09 +00:00
|
|
|
return generator_->FinalizeCode().ToHandleChecked();
|
2017-12-04 14:19:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Handle<Code> FinalizeForExecuting() {
|
2018-04-05 16:25:41 +00:00
|
|
|
// The test environment expects us to have performed moves on stack
|
|
|
|
// parameters. However, some of them are mapped to local spill slots. They
|
|
|
|
// should be moved back into stack parameters so their values are passed
|
|
|
|
// along to the `teardown` function.
|
|
|
|
for (auto move : spill_slots_) {
|
|
|
|
generator_->AssembleMove(&move.second, &move.first);
|
|
|
|
}
|
|
|
|
|
2019-02-12 09:38:11 +00:00
|
|
|
InstructionSequence* sequence = generator_->instructions();
|
2017-12-04 14:19:25 +00:00
|
|
|
|
|
|
|
sequence->StartBlock(RpoNumber::FromInt(0));
|
2017-10-11 10:22:40 +00:00
|
|
|
// The environment expects this code to tail-call to it's first parameter
|
|
|
|
// placed in `kReturnRegister0`.
|
2017-12-04 14:19:25 +00:00
|
|
|
sequence->AddInstruction(Instruction::New(zone_, kArchPrepareTailCall));
|
2017-10-11 10:22:40 +00:00
|
|
|
|
2017-12-04 14:19:25 +00:00
|
|
|
// We use either zero or one slots.
|
|
|
|
int first_unused_stack_slot =
|
|
|
|
V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0;
|
2017-12-15 17:01:32 +00:00
|
|
|
int optional_padding_slot = first_unused_stack_slot;
|
2017-10-11 10:22:40 +00:00
|
|
|
InstructionOperand callee[] = {
|
|
|
|
AllocatedOperand(LocationOperand::REGISTER,
|
|
|
|
MachineRepresentation::kTagged,
|
|
|
|
kReturnRegister0.code()),
|
[turbofan] IA32 port of branch load poisoning.
The tricky part here is to take away one register from register
allocation for the mask. The only problem is with calls that need
an input operand to be passed in the poison register. For such calls,
we change the register constraint in the instruction selector
to pass the value in whatever place the register allocator sees fit.
During code generation, we then copy the value from that place
to the poison register. By that time, the mask is not necessary
(once we bake the mask into the target, it should be done before
this move).
For the branches, the mask update does not use cmov (unlike x64)
because cmov does not take an immediate and we do not have
a scratch register. Instead we use bit-twiddling tricks
(suggested by @tebbi). For example, here is the code for masking
register update after a bailout on non-zero:
jnz deopt_bailout ;; Bailout branch
setnz bl ;; These three instructions update the mask
add ebx, 255
sar ebx, 31
(On x64, the sequence is:
jnz deopt_bailout
mov r10, 0 ;; We have a scratch register for zero
cmovnz r9, r10 ;; Set to zero if we execute this branch
;; in branch mis-speculation
)
This CL also fixes a bug in register configuration, where we used
to wrongly restrict the array of register name.
Change-Id: I5fceff2faf8bdc527d9934afc284b749574ab69e
Bug: chromium:798964
Reviewed-on: https://chromium-review.googlesource.com/946251
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51798}
2018-03-07 06:35:45 +00:00
|
|
|
ImmediateOperand(ImmediateOperand::INLINE, -1), // poison index.
|
2017-12-15 17:01:32 +00:00
|
|
|
ImmediateOperand(ImmediateOperand::INLINE, optional_padding_slot),
|
2017-12-04 14:19:25 +00:00
|
|
|
ImmediateOperand(ImmediateOperand::INLINE, first_unused_stack_slot)};
|
[turbofan] IA32 port of branch load poisoning.
The tricky part here is to take away one register from register
allocation for the mask. The only problem is with calls that need
an input operand to be passed in the poison register. For such calls,
we change the register constraint in the instruction selector
to pass the value in whatever place the register allocator sees fit.
During code generation, we then copy the value from that place
to the poison register. By that time, the mask is not necessary
(once we bake the mask into the target, it should be done before
this move).
For the branches, the mask update does not use cmov (unlike x64)
because cmov does not take an immediate and we do not have
a scratch register. Instead we use bit-twiddling tricks
(suggested by @tebbi). For example, here is the code for masking
register update after a bailout on non-zero:
jnz deopt_bailout ;; Bailout branch
setnz bl ;; These three instructions update the mask
add ebx, 255
sar ebx, 31
(On x64, the sequence is:
jnz deopt_bailout
mov r10, 0 ;; We have a scratch register for zero
cmovnz r9, r10 ;; Set to zero if we execute this branch
;; in branch mis-speculation
)
This CL also fixes a bug in register configuration, where we used
to wrongly restrict the array of register name.
Change-Id: I5fceff2faf8bdc527d9934afc284b749574ab69e
Bug: chromium:798964
Reviewed-on: https://chromium-review.googlesource.com/946251
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51798}
2018-03-07 06:35:45 +00:00
|
|
|
Instruction* tail_call =
|
|
|
|
Instruction::New(zone_, kArchTailCallCodeObject, 0, nullptr,
|
|
|
|
arraysize(callee), callee, 0, nullptr);
|
2017-12-04 14:19:25 +00:00
|
|
|
sequence->AddInstruction(tail_call);
|
|
|
|
sequence->EndBlock(RpoNumber::FromInt(0));
|
2017-08-30 12:09:00 +00:00
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
generator_->AssembleBlock(
|
2017-12-04 14:19:25 +00:00
|
|
|
sequence->InstructionBlockAt(RpoNumber::FromInt(0)));
|
|
|
|
|
|
|
|
return Finalize();
|
2017-07-13 09:55:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2017-10-11 10:22:40 +00:00
|
|
|
Zone* zone_;
|
2018-04-04 20:30:34 +00:00
|
|
|
OptimizedCompilationInfo info_;
|
2017-07-13 09:55:16 +00:00
|
|
|
Linkage linkage_;
|
|
|
|
Frame frame_;
|
2018-04-05 16:25:41 +00:00
|
|
|
CodeGenerator* generator_;
|
|
|
|
// List of operands to be moved from stack parameters to spill slots.
|
|
|
|
std::vector<std::pair<LocationOperand, LocationOperand>> spill_slots_;
|
2017-07-13 09:55:16 +00:00
|
|
|
};
|
|
|
|
|
2017-08-30 12:09:00 +00:00
|
|
|
// The following fuzz tests will assemble a lot of moves, wrap them in
|
2017-10-11 10:22:40 +00:00
|
|
|
// executable native code and run them. In order to check that moves were
|
|
|
|
// performed correctly, we need to setup an environment with an initial state
|
|
|
|
// and get it back after the list of moves were performed.
|
|
|
|
//
|
|
|
|
// We have two components to do this: TestEnvironment and CodeGeneratorTester.
|
|
|
|
//
|
|
|
|
// The TestEnvironment is in charge of bringing up an environment consisting of
|
|
|
|
// a set of registers, stack slots and constants, with initial values in
|
|
|
|
// them. The CodeGeneratorTester is a wrapper around the CodeGenerator and its
|
|
|
|
// only purpose is to generate code for a list of moves. The TestEnvironment is
|
|
|
|
// then able to run this code against the environment and return a resulting
|
|
|
|
// state.
|
|
|
|
//
|
|
|
|
// A "state" here is a packed FixedArray with tagged values which can either be
|
|
|
|
// Smis or HeapNumbers. When calling TestEnvironment::Run(...), registers and
|
|
|
|
// stack slots will be initialised according to this FixedArray. A new
|
|
|
|
// FixedArray is returned containing values that were moved by the generated
|
|
|
|
// code.
|
2017-10-17 17:28:35 +00:00
|
|
|
//
|
|
|
|
// And finally, we are able to compare the resulting FixedArray against a
|
|
|
|
// reference, computed with a simulation of AssembleMove and AssembleSwap. See
|
|
|
|
// SimulateMoves and SimulateSwaps.
|
2017-08-30 12:09:00 +00:00
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
// Allocate space between slots to increase coverage of moves with larger
|
|
|
|
// ranges. Note that this affects how much stack is allocated when running the
|
|
|
|
// generated code. It means we have to be careful not to exceed the stack limit,
|
|
|
|
// which is lower on Windows.
|
|
|
|
#ifdef V8_OS_WIN
|
|
|
|
constexpr int kExtraSpace = 0;
|
|
|
|
#else
|
|
|
|
constexpr int kExtraSpace = 1 * KB;
|
|
|
|
#endif
|
|
|
|
|
2017-08-30 12:09:00 +00:00
|
|
|
TEST(FuzzAssembleMove) {
|
2017-10-11 10:22:40 +00:00
|
|
|
TestEnvironment env;
|
|
|
|
|
|
|
|
Handle<FixedArray> state_in = env.GenerateInitialState();
|
|
|
|
ParallelMove* moves = env.GenerateRandomMoves(1000);
|
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
Handle<FixedArray> expected = env.SimulateMoves(moves, state_in);
|
2017-10-11 10:22:40 +00:00
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
// Test small and potentially large ranges separately.
|
|
|
|
for (int extra_space : {0, kExtraSpace}) {
|
|
|
|
CodeGeneratorTester c(&env, extra_space);
|
2017-10-11 10:22:40 +00:00
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
for (auto m : *moves) {
|
|
|
|
c.CheckAssembleMove(&m->source(), &m->destination());
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<Code> test = c.FinalizeForExecuting();
|
|
|
|
if (FLAG_print_code) {
|
2018-07-12 10:06:42 +00:00
|
|
|
test->Print();
|
2018-04-05 16:25:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Handle<FixedArray> actual = env.Run(test, state_in);
|
|
|
|
env.CheckState(actual, expected);
|
|
|
|
}
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(FuzzAssembleSwap) {
|
2017-10-11 10:22:40 +00:00
|
|
|
TestEnvironment env;
|
|
|
|
|
|
|
|
Handle<FixedArray> state_in = env.GenerateInitialState();
|
|
|
|
ParallelMove* swaps = env.GenerateRandomSwaps(1000);
|
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
Handle<FixedArray> expected = env.SimulateSwaps(swaps, state_in);
|
2017-10-11 10:22:40 +00:00
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
// Test small and potentially large ranges separately.
|
|
|
|
for (int extra_space : {0, kExtraSpace}) {
|
|
|
|
CodeGeneratorTester c(&env, extra_space);
|
2017-10-11 10:22:40 +00:00
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
for (auto s : *swaps) {
|
|
|
|
c.CheckAssembleSwap(&s->source(), &s->destination());
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<Code> test = c.FinalizeForExecuting();
|
|
|
|
if (FLAG_print_code) {
|
2018-07-12 10:06:42 +00:00
|
|
|
test->Print();
|
2018-04-05 16:25:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Handle<FixedArray> actual = env.Run(test, state_in);
|
|
|
|
env.CheckState(actual, expected);
|
|
|
|
}
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(FuzzAssembleMoveAndSwap) {
|
2017-10-11 10:22:40 +00:00
|
|
|
TestEnvironment env;
|
|
|
|
|
|
|
|
Handle<FixedArray> state_in = env.GenerateInitialState();
|
2017-10-17 17:28:35 +00:00
|
|
|
Handle<FixedArray> expected =
|
|
|
|
env.main_isolate()->factory()->NewFixedArray(state_in->length());
|
2018-04-05 16:25:41 +00:00
|
|
|
|
|
|
|
// Test small and potentially large ranges separately.
|
|
|
|
for (int extra_space : {0, kExtraSpace}) {
|
|
|
|
CodeGeneratorTester c(&env, extra_space);
|
|
|
|
|
|
|
|
state_in->CopyTo(0, *expected, 0, state_in->length());
|
|
|
|
|
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
// Randomly alternate between swaps and moves.
|
|
|
|
if (env.rng()->NextInt(2) == 0) {
|
|
|
|
ParallelMove* move = env.GenerateRandomMoves(1);
|
|
|
|
expected = env.SimulateMoves(move, expected);
|
|
|
|
c.CheckAssembleMove(&move->at(0)->source(),
|
|
|
|
&move->at(0)->destination());
|
|
|
|
} else {
|
|
|
|
ParallelMove* swap = env.GenerateRandomSwaps(1);
|
|
|
|
expected = env.SimulateSwaps(swap, expected);
|
|
|
|
c.CheckAssembleSwap(&swap->at(0)->source(),
|
|
|
|
&swap->at(0)->destination());
|
|
|
|
}
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
Handle<Code> test = c.FinalizeForExecuting();
|
|
|
|
if (FLAG_print_code) {
|
2018-07-12 10:06:42 +00:00
|
|
|
test->Print();
|
2018-04-05 16:25:41 +00:00
|
|
|
}
|
2017-10-11 10:22:40 +00:00
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
Handle<FixedArray> actual = env.Run(test, state_in);
|
|
|
|
env.CheckState(actual, expected);
|
|
|
|
}
|
2017-08-30 12:09:00 +00:00
|
|
|
}
|
|
|
|
|
2017-07-13 09:55:16 +00:00
|
|
|
TEST(AssembleTailCallGap) {
|
2018-10-02 14:24:19 +00:00
|
|
|
const RegisterConfiguration* conf = GetRegConfig();
|
2017-10-11 10:22:40 +00:00
|
|
|
TestEnvironment env;
|
2017-07-13 09:55:16 +00:00
|
|
|
|
|
|
|
// This test assumes at least 4 registers are allocatable.
|
2017-09-25 09:45:55 +00:00
|
|
|
CHECK_LE(4, conf->num_allocatable_general_registers());
|
2017-07-13 09:55:16 +00:00
|
|
|
|
|
|
|
auto r0 = AllocatedOperand(LocationOperand::REGISTER,
|
|
|
|
MachineRepresentation::kTagged,
|
|
|
|
conf->GetAllocatableGeneralCode(0));
|
|
|
|
auto r1 = AllocatedOperand(LocationOperand::REGISTER,
|
|
|
|
MachineRepresentation::kTagged,
|
|
|
|
conf->GetAllocatableGeneralCode(1));
|
|
|
|
auto r2 = AllocatedOperand(LocationOperand::REGISTER,
|
|
|
|
MachineRepresentation::kTagged,
|
|
|
|
conf->GetAllocatableGeneralCode(2));
|
|
|
|
auto r3 = AllocatedOperand(LocationOperand::REGISTER,
|
|
|
|
MachineRepresentation::kTagged,
|
|
|
|
conf->GetAllocatableGeneralCode(3));
|
|
|
|
|
|
|
|
auto slot_minus_4 = AllocatedOperand(LocationOperand::STACK_SLOT,
|
|
|
|
MachineRepresentation::kTagged, -4);
|
|
|
|
auto slot_minus_3 = AllocatedOperand(LocationOperand::STACK_SLOT,
|
|
|
|
MachineRepresentation::kTagged, -3);
|
|
|
|
auto slot_minus_2 = AllocatedOperand(LocationOperand::STACK_SLOT,
|
|
|
|
MachineRepresentation::kTagged, -2);
|
|
|
|
auto slot_minus_1 = AllocatedOperand(LocationOperand::STACK_SLOT,
|
|
|
|
MachineRepresentation::kTagged, -1);
|
|
|
|
|
|
|
|
// Avoid slot 0 for architectures which use it store the return address.
|
|
|
|
int first_slot = V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0;
|
|
|
|
auto slot_0 = AllocatedOperand(LocationOperand::STACK_SLOT,
|
|
|
|
MachineRepresentation::kTagged, first_slot);
|
|
|
|
auto slot_1 =
|
|
|
|
AllocatedOperand(LocationOperand::STACK_SLOT,
|
|
|
|
MachineRepresentation::kTagged, first_slot + 1);
|
|
|
|
auto slot_2 =
|
|
|
|
AllocatedOperand(LocationOperand::STACK_SLOT,
|
|
|
|
MachineRepresentation::kTagged, first_slot + 2);
|
|
|
|
auto slot_3 =
|
|
|
|
AllocatedOperand(LocationOperand::STACK_SLOT,
|
|
|
|
MachineRepresentation::kTagged, first_slot + 3);
|
|
|
|
|
|
|
|
// These tests all generate series of moves that the code generator should
|
|
|
|
// detect as adjacent pushes. Depending on the architecture, we make sure
|
|
|
|
// these moves get eliminated.
|
|
|
|
// Also, disassembling with `--print-code` is useful when debugging.
|
|
|
|
|
|
|
|
{
|
|
|
|
// Generate a series of register pushes only.
|
2017-10-11 10:22:40 +00:00
|
|
|
CodeGeneratorTester c(&env);
|
2017-12-04 14:19:25 +00:00
|
|
|
Instruction* instr = c.CreateTailCall(first_slot + 4);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(r3, slot_0);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(r2, slot_1);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(r1, slot_2);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(r0, slot_3);
|
|
|
|
|
|
|
|
c.CheckAssembleTailCallGaps(instr, first_slot + 4,
|
|
|
|
CodeGeneratorTester::kRegisterPush);
|
2017-10-11 10:22:40 +00:00
|
|
|
Handle<Code> code = c.Finalize();
|
|
|
|
if (FLAG_print_code) {
|
2018-07-12 10:06:42 +00:00
|
|
|
code->Print();
|
2017-10-11 10:22:40 +00:00
|
|
|
}
|
2017-07-13 09:55:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Generate a series of stack pushes only.
|
2017-10-11 10:22:40 +00:00
|
|
|
CodeGeneratorTester c(&env);
|
2017-12-04 14:19:25 +00:00
|
|
|
Instruction* instr = c.CreateTailCall(first_slot + 4);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(slot_minus_4, slot_0);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(slot_minus_3, slot_1);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(slot_minus_2, slot_2);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(slot_minus_1, slot_3);
|
|
|
|
|
|
|
|
c.CheckAssembleTailCallGaps(instr, first_slot + 4,
|
|
|
|
CodeGeneratorTester::kStackSlotPush);
|
2017-10-11 10:22:40 +00:00
|
|
|
Handle<Code> code = c.Finalize();
|
|
|
|
if (FLAG_print_code) {
|
2018-07-12 10:06:42 +00:00
|
|
|
code->Print();
|
2017-10-11 10:22:40 +00:00
|
|
|
}
|
2017-07-13 09:55:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Generate a mix of stack and register pushes.
|
2017-10-11 10:22:40 +00:00
|
|
|
CodeGeneratorTester c(&env);
|
2017-12-04 14:19:25 +00:00
|
|
|
Instruction* instr = c.CreateTailCall(first_slot + 4);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(slot_minus_2, slot_0);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(r1, slot_1);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(slot_minus_1, slot_2);
|
2017-08-30 12:09:00 +00:00
|
|
|
instr
|
|
|
|
->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
|
2017-10-11 10:22:40 +00:00
|
|
|
env.main_zone())
|
2017-07-13 09:55:16 +00:00
|
|
|
->AddMove(r0, slot_3);
|
|
|
|
|
|
|
|
c.CheckAssembleTailCallGaps(instr, first_slot + 4,
|
|
|
|
CodeGeneratorTester::kScalarPush);
|
2017-10-11 10:22:40 +00:00
|
|
|
Handle<Code> code = c.Finalize();
|
|
|
|
if (FLAG_print_code) {
|
2018-07-12 10:06:42 +00:00
|
|
|
code->Print();
|
2017-10-11 10:22:40 +00:00
|
|
|
}
|
2017-07-13 09:55:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|