Skip to content

Commit 273f524

Browse files
jjgriegojustinmichaud
authored andcommitted
[ARMv7] Support running testb3
https://bugs.webkit.org/show_bug.cgi?id=276367 Reviewed by OOPS. This patch was written by Joseph Griego a while back. This does the following: - Support running testb3 on armv7 - Allow dumping testb3 output, to ensure these changes don't affect other platforms testb3 does not pass fully yet, but it does pass simple tests like testRotR. I also added a list of skipped subtests, and confirmed on x86_64 and ARM64 (non-E) that the generated B3 code is not changed. To make these tests run, we mostly just abstract the calling convention away. Every other change is mechanical. Canonical link: https://commits.webkit.org/282881@main
1 parent d1ee6bc commit 273f524

20 files changed

Lines changed: 4223 additions & 2929 deletions

‎Source/JavaScriptCore/b3/B3Generate.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ void generateToAir(Procedure& procedure)
106106

107107
#if USE(JSVALUE32_64)
108108
lowerInt64(procedure);
109+
if (procedure.optLevel() >= 2)
110+
reduceStrength(procedure);
109111
#endif
110112

111113
if (procedure.optLevel() >= 2) {

‎Source/JavaScriptCore/b3/B3LowerToAir32_64.cpp‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ struct MaybeWide {
8585
void dump(PrintStream& out) const
8686
{
8787
if (!*this)
88-
out.print("(<none>)");
88+
out.print("(<none (maybewide)>)");
8989
else if (inner.index() == 1)
9090
out.print("(", std::get<1>(inner), ")");
9191
else {
@@ -501,7 +501,7 @@ class LowerToAir {
501501
}
502502
return tmp;
503503
}
504-
Arg someArg(Value *value)
504+
Arg someArg(Value* value)
505505
{
506506
LogicalTmp tmp = someTmp(value);
507507
if (tmp.isNarrow())
@@ -1665,7 +1665,7 @@ class LowerToAir {
16651665
break;
16661666
case ValueRep::SomeRegister:
16671667
case ValueRep::SomeLateRegister:
1668-
arg = tmp(value.value());
1668+
arg = someArg(value.value());
16691669
break;
16701670
case ValueRep::SomeRegisterWithClobber: {
16711671
Tmp dstTmp = m_code.newTmp(value.value()->resultBank());
@@ -4882,6 +4882,7 @@ class LowerToAir {
48824882
inst.args.append(arg.tmp());
48834883
return;
48844884
case ValueRep::Register: {
4885+
RELEASE_ASSERT(!is32Bit() || type != Int64);
48854886
Tmp reg = Tmp(rep.reg());
48864887
inst.args.append(reg);
48874888
after.append(Inst(relaxedMoveForType(type), m_value, reg, arg.tmp()));

‎Source/JavaScriptCore/b3/B3Procedure.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ class Procedure {
282282
JS_EXPORT_PRIVATE void freeUnneededB3ValuesAfterLowering();
283283

284284
bool shouldDumpIR() const { return m_shouldDumpIR; }
285-
void setShouldDumpIR();
285+
JS_EXPORT_PRIVATE void setShouldDumpIR();
286286

287287
void setUsessSIMD()
288288
{

‎Source/JavaScriptCore/b3/air/AirCCallingConvention.cpp‎

Lines changed: 102 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030

3131
#include "AirCCallSpecial.h"
3232
#include "AirCode.h"
33+
#include "B3ArgumentRegValue.h"
34+
#include "B3AtomicValue.h"
35+
#include "B3BasicBlockInlines.h"
36+
#include "B3BreakCriticalEdges.h"
3337
#include "B3CCallValue.h"
3438
#include "B3Procedure.h"
3539

@@ -38,10 +42,10 @@ namespace JSC { namespace B3 { namespace Air {
3842
namespace {
3943

4044
template<typename BankInfo>
41-
void marshallCCallArgumentImpl(Vector<Arg>& result, unsigned& argumentCount, unsigned& stackOffset, Value* child)
45+
void marshallCCallArgumentImpl(Vector<Arg>& result, unsigned& argumentCount, unsigned& stackOffset, Type childType)
4246
{
43-
const auto registerCount = cCallArgumentRegisterCount(child);
44-
if (is32Bit() && child->type() == Int64)
47+
const auto registerCount = cCallArgumentRegisterCount(childType);
48+
if (is32Bit() && childType == Int64)
4549
argumentCount = WTF::roundUpToMultipleOf<2>(argumentCount);
4650

4751
if (argumentCount < BankInfo::numberOfArgumentRegisters) {
@@ -57,10 +61,10 @@ void marshallCCallArgumentImpl(Vector<Arg>& result, unsigned& argumentCount, uns
5761
// In the rare case when the Arg width does not match the argument width
5862
// (32-bit arm passing a 64-bit argument), we respect the width needed
5963
// for each stack access:
60-
slotSize = bytesForWidth(cCallArgumentRegisterWidth(child->type()));
64+
slotSize = bytesForWidth(cCallArgumentRegisterWidth(childType));
6165

6266
// but the logical stack slot uses the natural alignment of the argument
63-
slotAlignment = sizeofType(child->type());
67+
slotAlignment = sizeofType(childType);
6468

6569
} else {
6670
// On other platforms, arguments are always aligned to machine word
@@ -76,14 +80,15 @@ void marshallCCallArgumentImpl(Vector<Arg>& result, unsigned& argumentCount, uns
7680
}
7781
}
7882

79-
void marshallCCallArgument(Vector<Arg> &result, unsigned& gpArgumentCount, unsigned& fpArgumentCount, unsigned& stackOffset, Value* child)
83+
84+
void marshallCCallArgument(Vector<Arg> &result, unsigned& gpArgumentCount, unsigned& fpArgumentCount, unsigned& stackOffset, Type childType)
8085
{
81-
switch (bankForType(child->type())) {
86+
switch (bankForType(childType)) {
8287
case GP:
83-
marshallCCallArgumentImpl<GPRInfo>(result, gpArgumentCount, stackOffset, child);
88+
marshallCCallArgumentImpl<GPRInfo>(result, gpArgumentCount, stackOffset, childType);
8489
return;
8590
case FP:
86-
marshallCCallArgumentImpl<FPRInfo>(result, fpArgumentCount, stackOffset, child);
91+
marshallCCallArgumentImpl<FPRInfo>(result, fpArgumentCount, stackOffset, childType);
8792
return;
8893
}
8994
RELEASE_ASSERT_NOT_REACHED();
@@ -99,7 +104,7 @@ Vector<Arg> computeCCallingConvention(Code& code, CCallValue* value)
99104
unsigned fpArgumentCount = 0;
100105
unsigned stackOffset = 0;
101106
for (unsigned i = 1; i < value->numChildren(); ++i)
102-
marshallCCallArgument(result, gpArgumentCount, fpArgumentCount, stackOffset, value->child(i));
107+
marshallCCallArgument(result, gpArgumentCount, fpArgumentCount, stackOffset, value->child(i)->type());
103108
code.requestCallArgAreaSizeInBytes(WTF::roundUpToMultipleOf<stackAlignmentBytes()>(stackOffset));
104109
return result;
105110
}
@@ -129,9 +134,9 @@ size_t cCallResultCount(Code& code, CCallValue* value)
129134
}
130135
}
131136

132-
size_t cCallArgumentRegisterCount(const Value* value)
137+
size_t cCallArgumentRegisterCount(Type type)
133138
{
134-
switch (value->type().kind()) {
139+
switch (type.kind()) {
135140
case Void:
136141
return 0;
137142
case Int64:
@@ -203,6 +208,91 @@ Inst buildCCall(Code& code, Value* origin, const Vector<Arg>& arguments)
203208
return inst;
204209
}
205210

211+
#if CPU(ARM_THUMB2)
212+
Value* ArgumentValueList::makeStitch(B3::BasicBlock*, Value* hi, Value* low) const
213+
{
214+
return block->appendNew<Value>(procedure, Stitch, Origin(), hi, low);
215+
}
216+
#endif
217+
218+
Value* ArgumentValueList::makeCCallValue(B3::BasicBlock* block, Type type, Air::Arg arg) const
219+
{
220+
if (arg.isTmp() && arg.tmp().isReg()) {
221+
Value* val = block->appendNew<ArgumentRegValue>(procedure, Origin(), arg.reg());
222+
if constexpr (!is32Bit()) {
223+
if (type == Int32)
224+
val = block->appendNew<Value>(procedure, Trunc, Origin(), val);
225+
}
226+
227+
if (type == Float)
228+
val = block->appendNew<Value>(procedure, Trunc, Origin(), val);
229+
230+
return val;
231+
}
232+
233+
// we really shouldn't be using this except on arm32, so, assert just in
234+
// case, since the details are likely wrong for other architectures, and
235+
// it's not expected to end up here on 64-bit
236+
RELEASE_ASSERT(isARM_THUMB2() && arg.isCallArg());
237+
238+
return block->appendNew<MemoryValue>(procedure,
239+
Load,
240+
type,
241+
Origin(),
242+
block->appendNew<Value>(procedure, FramePointer, Origin()),
243+
arg.offset() + 2 * sizeof(void*)
244+
);
245+
}
246+
247+
Value* ArgumentValueList::makeCCallValue(B3::BasicBlock* block, size_t idx) const
248+
{
249+
unsigned firstUnderlyingArg = argUnderlyingCounts[idx];
250+
unsigned argCount = 0;
251+
if (idx + 1 < types.size())
252+
argCount = argUnderlyingCounts[idx + 1] - firstUnderlyingArg;
253+
else
254+
argCount = underlyingArgs.size() - firstUnderlyingArg;
255+
RELEASE_ASSERT(firstUnderlyingArg < underlyingArgs.size());
256+
RELEASE_ASSERT(firstUnderlyingArg + argCount <= underlyingArgs.size());
257+
258+
switch (types[idx].kind()) {
259+
case Int32:
260+
case Float:
261+
case Double:
262+
RELEASE_ASSERT(argCount == 1);
263+
return makeCCallValue(block, types[idx], underlyingArgs[firstUnderlyingArg]);
264+
265+
case Int64:
266+
RELEASE_ASSERT(argCount == sizeof(uint64_t) / sizeof(uintptr_t));
267+
#if CPU(ARM_THUMB2)
268+
return makeStitch(block, makeCCallValue(block, types[idx], underlyingArgs[firstUnderlyingArg + 1]),
269+
makeCCallValue(block, types[idx], underlyingArgs[firstUnderlyingArg]));
270+
#else
271+
return makeCCallValue(block, types[idx], underlyingArgs[firstUnderlyingArg]);
272+
#endif
273+
274+
default:
275+
RELEASE_ASSERT_NOT_REACHED();
276+
return nullptr;
277+
}
278+
}
279+
280+
ArgumentValueList computeCCallArguments(Procedure& procedure, B3::BasicBlock* block, const Vector<Type>& types)
281+
{
282+
Vector<Air::Arg> underlyingArgs;
283+
Vector<unsigned> argUnderlyingCounts;
284+
unsigned gpArgumentCount = 0;
285+
unsigned fpArgumentCount = 0;
286+
unsigned stackOffset = 0;
287+
288+
for (auto type : types) {
289+
argUnderlyingCounts.append(underlyingArgs.size());
290+
marshallCCallArgument(underlyingArgs, gpArgumentCount, fpArgumentCount, stackOffset, type);
291+
}
292+
293+
return ArgumentValueList { procedure, block, types, WTFMove(underlyingArgs), WTFMove(argUnderlyingCounts) };
294+
}
295+
206296
} } } // namespace JSC::B3::Air
207297

208298
#endif // ENABLE(B3_JIT)

‎Source/JavaScriptCore/b3/air/AirCCallingConvention.h‎

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
namespace JSC { namespace B3 {
3636

3737
class CCallValue;
38+
class BasicBlock;
3839

3940
namespace Air {
4041

@@ -52,14 +53,72 @@ size_t cCallResultCount(Code&, CCallValue*);
5253
*/
5354

5455
// Return the number of Air::Args needed to marshall this Value to the C function
55-
size_t cCallArgumentRegisterCount(const Value*);
56+
size_t cCallArgumentRegisterCount(Type);
5657
// Return the width of the individual Air::Args needed to marshall this value
5758
Width cCallArgumentRegisterWidth(Type);
5859

5960
Tmp cCallResult(Code&, CCallValue*, unsigned);
6061

6162
Inst buildCCall(Code&, Value* origin, const Vector<Arg>&);
6263

64+
template<unsigned size> constexpr inline Type b3IntegerType;
65+
template<> constexpr inline Type b3IntegerType<4> = Int32;
66+
template<> constexpr inline Type b3IntegerType<8> = Int64;
67+
68+
template<typename T> constexpr inline Type b3Type;
69+
template<> constexpr inline Type b3Type<int> = b3IntegerType<sizeof(int)>;
70+
template<> constexpr inline Type b3Type<long> = b3IntegerType<sizeof(long)>;
71+
template<> constexpr inline Type b3Type<long long> = b3IntegerType<sizeof(long long)>;
72+
template<> constexpr inline Type b3Type<unsigned> = b3IntegerType<sizeof(unsigned)>;
73+
template<> constexpr inline Type b3Type<unsigned long> = b3IntegerType<sizeof(unsigned long)>;
74+
template<> constexpr inline Type b3Type<unsigned long long> = b3IntegerType<sizeof(unsigned long long)>;
75+
template<> constexpr inline Type b3Type<float> = Float;
76+
template<> constexpr inline Type b3Type<double> = Double;
77+
template<typename T> constexpr inline Type b3Type<T*> = pointerType();
78+
79+
// This maps between B3 args and air args.
80+
// On 32-bit platforms only, this may be an n:m mapping.
81+
struct ArgumentValueList {
82+
#if CPU(ARM_THUMB2)
83+
JS_EXPORT_PRIVATE Value* makeStitch(B3::BasicBlock*, Value* hi, Value* low) const;
84+
#endif
85+
JS_EXPORT_PRIVATE Value* makeCCallValue(B3::BasicBlock*, Type, Air::Arg) const;
86+
JS_EXPORT_PRIVATE Value* makeCCallValue(B3::BasicBlock*, size_t idx) const;
87+
88+
inline Value* operator[](size_t idx) const
89+
{
90+
return makeCCallValue(block, idx);
91+
}
92+
93+
inline Value* withBlock(B3::BasicBlock *bb, size_t idx) const
94+
{
95+
return makeCCallValue(bb, idx);
96+
}
97+
98+
inline Vector<Value*> eager() const
99+
{
100+
Vector<Value*> result;
101+
for (size_t i = 0; i < types.size(); ++i)
102+
result.append(makeCCallValue(block, i));
103+
return result;
104+
}
105+
106+
Procedure& procedure;
107+
B3::BasicBlock* block;
108+
109+
Vector<Type> types;
110+
Vector<Air::Arg> underlyingArgs;
111+
Vector<unsigned> argUnderlyingCounts;
112+
};
113+
114+
JS_EXPORT_PRIVATE ArgumentValueList computeCCallArguments(Procedure&, B3::BasicBlock*, const Vector<Type>&);
115+
116+
template<typename ... T>
117+
ArgumentValueList cCallArgumentValues(Procedure& procedure, B3::BasicBlock* block)
118+
{
119+
return computeCCallArguments(procedure, block, { b3Type<T> ... });
120+
}
121+
63122
} } } // namespace JSC::B3::Air
64123

65124
#endif // ENABLE(B3_JIT)

‎Source/JavaScriptCore/b3/air/AirCustom.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ bool CCallCustom::isValidForm(Inst& inst)
7676
size_t expectedArgCount = resultCount + 1; // first Arg is always CCallSpecial.
7777
for (Value* child : value->children()) {
7878
ASSERT(!child->type().isTuple());
79-
expectedArgCount += cCallArgumentRegisterCount(child);
79+
expectedArgCount += cCallArgumentRegisterCount(child->type());
8080
}
8181

8282
if (inst.args.size() != expectedArgCount)
@@ -115,7 +115,7 @@ bool CCallCustom::isValidForm(Inst& inst)
115115

116116
for (unsigned i = 1 ; i < value->numChildren(); ++i) {
117117
Value* child = value->child(i);
118-
for (unsigned j = 0; j < cCallArgumentRegisterCount(child); j++) {
118+
for (unsigned j = 0; j < cCallArgumentRegisterCount(child->type()); j++) {
119119
if (!checkNextArg(child))
120120
return false;
121121
}

‎Source/JavaScriptCore/b3/air/AirCustom.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ struct CCallCustom : public CommonCustomBase<CCallCustom> {
157157

158158
for (unsigned i = 1; i < value->numChildren(); ++i) {
159159
Value* child = value->child(i);
160-
for (size_t j = 0; j < cCallArgumentRegisterCount(child); j++) {
160+
for (size_t j = 0; j < cCallArgumentRegisterCount(child->type()); j++) {
161161
next(
162162
Arg::Use,
163163
bankForType(child->type()),

‎Source/JavaScriptCore/b3/air/AirLowerMacros.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ void lowerMacros(Code& code)
6868
};
6969
for (unsigned i = 1; i < value->numChildren(); ++i) {
7070
Value* child = value->child(i);
71-
for (unsigned j = 0; j < cCallArgumentRegisterCount(child); j++)
71+
for (unsigned j = 0; j < cCallArgumentRegisterCount(child->type()); j++)
7272
addNextPair(cCallArgumentRegisterWidth(child->type()));
7373
}
7474
ASSERT(offset = inst.args.size());

0 commit comments

Comments
 (0)