Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf35c5dd

Browse files
committed
WiP Redesign the encoding of Longs in JavaScript.
As a nice bonus, the IR checker now passes with `RuntimeLong`.
1 parent331baa8 commitf35c5dd

File tree

19 files changed

+1561
-1107
lines changed

19 files changed

+1561
-1107
lines changed

‎linker-private-library/src/main/scala/org/scalajs/linker/runtime/RuntimeLong.scala

Lines changed: 196 additions & 361 deletions
Large diffs are not rendered by default.

‎linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/ClassEmitter.scala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,17 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
371371
}yield {
372372
valfield= anyField.asInstanceOf[FieldDef]
373373
implicitvalpos= field.pos
374-
js.Assign(genSelectForDef(js.This(), field.name, field.originalName),
375-
genZeroOf(field.ftpe))
374+
field.ftpematch {
375+
caseLongTypeif!useBigIntForLongs=>
376+
val (lo, hi)= genSelectLongForDef(js.This(), field.name, field.originalName)
377+
js.Block(
378+
js.Assign(lo, js.IntLiteral(0)),
379+
js.Assign(hi, js.IntLiteral(0))
380+
)
381+
case _=>
382+
js.Assign(genSelectForDef(js.This(), field.name, field.originalName),
383+
genZeroOf(field.ftpe))
384+
}
376385
}
377386
}
378387

‎linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/CoreJSLib.scala

Lines changed: 197 additions & 54 deletions
Large diffs are not rendered by default.

‎linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/Emitter.scala

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,12 +1434,7 @@ object Emitter {
14341434
callMethod(BoxedStringClass, hashCodeMethodName),
14351435

14361436
cond(!config.coreSpec.esFeatures.allowBigIntsForLongs) {
1437-
multiple(
1438-
instanceTests(LongImpl.RuntimeLongClass),
1439-
instantiateClass(LongImpl.RuntimeLongClass,LongImpl.AllConstructors.toList),
1440-
callMethods(LongImpl.RuntimeLongClass,LongImpl.BoxedLongMethods.toList),
1441-
callStaticMethods(LongImpl.RuntimeLongClass,LongImpl.OperatorMethods.toList)
1442-
)
1437+
callStaticMethods(LongImpl.RuntimeLongClass,LongImpl.OperatorMethods.toList)
14431438
},
14441439

14451440
cond(config.coreSpec.esFeatures.esVersion<ESVersion.ES2015) {

‎linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/FunctionEmitter.scala

Lines changed: 728 additions & 313 deletions
Large diffs are not rendered by default.

‎linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/LongImpl.scala

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import org.scalajs.ir.WellKnownNames._
1818

1919
private[linker]objectLongImpl {
2020
finalvalRuntimeLongClass=ClassName("org.scalajs.linker.runtime.RuntimeLong")
21+
finalvalRuntimeLongModClass=ClassName("org.scalajs.linker.runtime.RuntimeLong$")
2122

2223
finalvallo=MethodName("lo",Nil,IntRef)
2324
finalvalhi=MethodName("hi",Nil,IntRef)
@@ -26,35 +27,23 @@ private[linker] object LongImpl {
2627
privatefinalvalOneRTLongRef=RTLongRef::Nil
2728
privatefinalvalTwoRTLongRefs=RTLongRef::OneRTLongRef
2829

30+
privatefinalvalTwoIntRefs=IntRef::IntRef::Nil
31+
privatefinalvalThreeIntRefs=IntRef::TwoIntRefs
32+
privatefinalvalFourIntRefs=IntRef::ThreeIntRefs
33+
34+
finalvalpack=MethodName("pack",TwoIntRefs,LongRef)
35+
2936
defunaryOp(name:String):MethodName=
30-
MethodName(name,OneRTLongRef,RTLongRef)
37+
MethodName(name,TwoIntRefs,LongRef)
3138

3239
defbinaryOp(name:String):MethodName=
33-
MethodName(name,TwoRTLongRefs,RTLongRef)
40+
MethodName(name,FourIntRefs,LongRef)
3441

3542
defshiftOp(name:String):MethodName=
36-
MethodName(name,List(RTLongRef,IntRef),RTLongRef)
43+
MethodName(name,ThreeIntRefs,LongRef)
3744

3845
defcompareOp(name:String):MethodName=
39-
MethodName(name,TwoRTLongRefs,BooleanRef)
40-
41-
// Instance methods that we need to reach as part of the jl.Long boxing
42-
43-
privatefinalvalbyteValue=MethodName("byteValue",Nil,ByteRef)
44-
privatefinalvalshortValue=MethodName("shortValue",Nil,ShortRef)
45-
privatefinalvalintValue=MethodName("intValue",Nil,IntRef)
46-
privatefinalvallongValue=MethodName("longValue",Nil,LongRef)
47-
privatefinalvalfloatValue=MethodName("floatValue",Nil,FloatRef)
48-
privatefinalvaldoubleValue=MethodName("doubleValue",Nil,DoubleRef)
49-
50-
privatefinalvalequalsO=MethodName("equals",List(ClassRef(ObjectClass)),BooleanRef)
51-
privatefinalvalhashCode_=MethodName("hashCode",Nil,IntRef)
52-
privatefinalvalcompareTo=MethodName("compareTo",List(ClassRef(BoxedLongClass)),IntRef)
53-
privatefinalvalcompareToO=MethodName("compareTo",List(ClassRef(ObjectClass)),IntRef)
54-
55-
valBoxedLongMethods=Set(
56-
byteValue, shortValue, intValue, longValue, floatValue, doubleValue,
57-
equalsO, hashCode_, compareTo, compareToO)
46+
MethodName(name,FourIntRefs,BooleanRef)
5847

5948
// Operator methods
6049

@@ -86,49 +75,42 @@ private[linker] object LongImpl {
8675
finalvalgtu= compareOp("gtu")
8776
finalvalgeu= compareOp("geu")
8877

89-
finalvaltoInt=MethodName("toInt",OneRTLongRef,IntRef)
90-
finalvaltoFloat=MethodName("toFloat",OneRTLongRef,FloatRef)
91-
finalvaltoDouble=MethodName("toDouble",OneRTLongRef,DoubleRef)
92-
finalvalbitsToDouble=MethodName("bitsToDouble",List(RTLongRef,ObjectRef),DoubleRef)
93-
finalvalclz=MethodName("clz",OneRTLongRef,IntRef)
78+
finalvaltoInt=MethodName("toInt",TwoIntRefs,IntRef)
79+
finalvaltoFloat=MethodName("toFloat",TwoIntRefs,FloatRef)
80+
finalvaltoDouble=MethodName("toDouble",TwoIntRefs,DoubleRef)
81+
finalvalbitsToDouble=MethodName("bitsToDouble",List(IntRef,IntRef,ObjectRef),DoubleRef)
82+
finalvalclz=MethodName("clz",TwoIntRefs,IntRef)
9483

95-
finalvalfromInt=MethodName("fromInt",List(IntRef),RTLongRef)
96-
finalvalfromUnsignedInt=MethodName("fromUnsignedInt",List(IntRef),RTLongRef)
97-
finalvalfromDouble=MethodName("fromDouble",List(DoubleRef),RTLongRef)
98-
finalvalfromDoubleBits=MethodName("fromDoubleBits",List(DoubleRef,ObjectRef),RTLongRef)
84+
finalvalfromInt=MethodName("fromInt",List(IntRef),LongRef)
85+
finalvalfromUnsignedInt=MethodName("fromUnsignedInt",List(IntRef),LongRef)
86+
finalvalfromDouble=MethodName("fromDouble",List(DoubleRef),LongRef)
87+
finalvalfromDoubleBits=MethodName("fromDoubleBits",List(DoubleRef,ObjectRef),LongRef)
88+
89+
finalvaltoString_=MethodName("toString",TwoIntRefs,ClassRef(BoxedStringClass))
9990

10091
valOperatorMethods=Set(
10192
add, sub, mul,
10293
divide, remainder, divideUnsigned, remainderUnsigned,
10394
or, and, xor, shl, shr, sar,
10495
equals_, notEquals, lt, le, gt, ge, ltu, leu, gtu, geu,
10596
toInt, toFloat, toDouble, bitsToDouble, clz,
106-
fromInt, fromUnsignedInt, fromDouble, fromDoubleBits
97+
fromInt, fromUnsignedInt, fromDouble, fromDoubleBits,
98+
toString_
10799
)
108100

109101
// Methods used for intrinsics
110102

111-
finalvaltoString_=MethodName("toString",OneRTLongRef,ClassRef(BoxedStringClass))
112-
113-
finalvalcompare=MethodName("compare",TwoRTLongRefs,IntRef)
103+
finalvalcompare=MethodName("compare",FourIntRefs,IntRef)
114104

115-
finalvalabs=MethodName("abs",OneRTLongRef,RTLongRef)
116-
finalvalmultiplyFull=MethodName("multiplyFull",List(IntRef,IntRef),RTLongRef)
105+
finalvalabs=MethodName("abs",TwoIntRefs,LongRef)
106+
finalvalmultiplyFull=MethodName("multiplyFull",TwoIntRefs,LongRef)
117107

118108
valAllIntrinsicMethods=Set(
119-
toString_,
120109
compare,
121110
abs,
122111
multiplyFull
123112
)
124113

125-
// Constructors
126-
127-
finalvalinitFromParts=MethodName.constructor(List(IntRef,IntRef))
128-
129-
valAllConstructors=Set(
130-
initFromParts)
131-
132114
// Extract the parts to give to the initFromParts constructor
133115

134116
defextractParts(value:Long): (Int,Int)=

‎linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/SJSGen.scala

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ private[emitter] final class SJSGen(
5757
/** `Char.c`: the int value of the character.*/
5858
valc="c"
5959

60+
/** `Long.l`: the lo word of the long.*/
61+
vallo="l"
62+
63+
/** `Long.h`: the hi word of the long.*/
64+
valhi="h"
65+
6066
// --- TypeData fields ---
6167

6268
/** `TypeData.constr`: the run-time constructor of the class.*/
@@ -222,23 +228,18 @@ private[emitter] final class SJSGen(
222228
defgenLongZero()(
223229
implicitmoduleContext:ModuleContext,globalKnowledge:GlobalKnowledge,
224230
pos:Position):Tree= {
225-
if (useBigIntForLongs)
226-
BigIntLiteral(0L)
227-
else
228-
globalVar(VarField.L0,CoreVar)
231+
assert(useBigIntForLongs,s"cannot generate a zero value for primitive long at$pos")
232+
BigIntLiteral(0L)
229233
}
230234

231235
defgenBoxedZeroOf(tpe:Type)(
232236
implicitmoduleContext:ModuleContext,globalKnowledge:GlobalKnowledge,
233237
pos:Position):Tree= {
234-
if (tpe==CharType) genBoxedCharZero()
235-
else genZeroOf(tpe)
236-
}
237-
238-
defgenBoxedCharZero()(
239-
implicitmoduleContext:ModuleContext,globalKnowledge:GlobalKnowledge,
240-
pos:Position):Tree= {
241-
globalVar(VarField.bC0,CoreVar)
238+
tpematch {
239+
caseCharType=> globalVar(VarField.bC0,CoreVar)
240+
caseLongTypeif!useBigIntForLongs=> globalVar(VarField.bL0,CoreVar)
241+
case _=> genZeroOf(tpe)
242+
}
242243
}
243244

244245
defgenLongApplyStatic(methodName:MethodName,args:Tree*)(
@@ -278,7 +279,11 @@ private[emitter] final class SJSGen(
278279
caseFloatRef=> some("Float32Array")
279280
caseDoubleRef=> some("Float64Array")
280281

281-
caseLongRefif useBigIntForLongs=> some("BigInt64Array")
282+
caseLongRef=>
283+
if (useBigIntForLongs)
284+
some("BigInt64Array")
285+
else
286+
some("Int32Array")// where elements are spread over two slots
282287

283288
case _=>None
284289
}
@@ -289,12 +294,28 @@ private[emitter] final class SJSGen(
289294
DotSelect(receiver, genFieldIdent(field.name)(field.pos))
290295
}
291296

297+
defgenSelectLong(receiver:Tree,field: irt.FieldIdent)(
298+
implicitpos:Position): (Tree,Tree)= {
299+
// TODO Name compressor
300+
valbaseName= genName(field.name)
301+
valloIdent=Ident(baseName+"_$lo")(field.pos)
302+
valhiIdent=Ident(baseName+"_$hi")(field.pos)
303+
(DotSelect(receiver, loIdent),DotSelect(receiver, hiIdent))
304+
}
305+
292306
defgenSelectForDef(receiver:Tree,field: irt.FieldIdent,
293307
originalName:OriginalName)(
294308
implicitpos:Position):Tree= {
295309
DotSelect(receiver, genFieldIdentForDef(field.name, originalName)(field.pos))
296310
}
297311

312+
defgenSelectLongForDef(receiver:Tree,field: irt.FieldIdent,
313+
originalName:OriginalName)(
314+
implicitpos:Position): (Tree,Tree)= {
315+
// TODO Name compressor; originalName
316+
genSelectLong(receiver, field)
317+
}
318+
298319
privatedefgenFieldIdent(fieldName:FieldName)(
299320
implicitpos:Position):MaybeDelayedIdent= {
300321
nameCompressormatch {
@@ -488,7 +509,7 @@ private[emitter] final class SJSGen(
488509
importTreeDSL._
489510

490511
if (useBigIntForLongs) genCallHelper(VarField.isLong, expr)
491-
else expr instanceof globalVar(VarField.c,LongImpl.RuntimeLongClass)
512+
else expr instanceof globalVar(VarField.Long,CoreVar)
492513
}
493514

494515
defgenAsInstanceOf(expr:Tree,tpe:Type)(

‎linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/Transients.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,47 @@ import org.scalajs.ir.Types._
2121

2222
objectTransients {
2323

24+
/** Packs a `long` value from its `lo` and `hi` words.*/
25+
finalcaseclassPackLong(lo:Tree,hi:Tree)extendsTransient.Value {
26+
valtpe=LongType
27+
28+
deftraverse(traverser:Traverser):Unit= {
29+
traverser.traverse(lo)
30+
traverser.traverse(hi)
31+
}
32+
33+
deftransform(transformer:Transformer)(implicitpos:Position):Tree=
34+
Transient(PackLong(transformer.transform(lo), transformer.transform(hi)))
35+
36+
defprintIR(out:IRTreePrinter):Unit= {
37+
out.print("<packLong>(")
38+
out.print(lo)
39+
out.print(",")
40+
out.print(hi)
41+
out.print(")")
42+
}
43+
}
44+
45+
/** Extracts the `hi` word of a `long` value.
46+
*
47+
* To extract the `lo` word, use a `UnaryOp.LongToInt`.
48+
*/
49+
finalcaseclassExtractLongHi(value:Tree)extendsTransient.Value {
50+
valtpe=IntType
51+
52+
deftraverse(traverser:Traverser):Unit=
53+
traverser.traverse(value)
54+
55+
deftransform(transformer:Transformer)(implicitpos:Position):Tree=
56+
Transient(ExtractLongHi(transformer.transform(value)))
57+
58+
defprintIR(out:IRTreePrinter):Unit= {
59+
out.print("<hi>(")
60+
out.print(value)
61+
out.print(")")
62+
}
63+
}
64+
2465
/** Casts `expr` to the given `tpe`, without any check.
2566
*
2667
* This operation is only valid if we know that `expr` is indeed a value of

‎linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/TreeDSL.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ private[emitter] object TreeDSL {
5757

5858
def+(that:Tree)(implicitpos:Position):Tree=
5959
BinaryOp(ir.Trees.JSBinaryOp.+, self, that)
60+
def+(that:Int)(implicitpos:Position):Tree=
61+
BinaryOp(ir.Trees.JSBinaryOp.+, self,IntLiteral(that))
6062
def-(that:Tree)(implicitpos:Position):Tree=
6163
BinaryOp(ir.Trees.JSBinaryOp.-, self, that)
6264
def*(that:Tree)(implicitpos:Position):Tree=
@@ -77,6 +79,8 @@ private[emitter] object TreeDSL {
7779

7880
def<<(that:Tree)(implicitpos:Position):Tree=
7981
BinaryOp(ir.Trees.JSBinaryOp.<<, self, that)
82+
def<<(that:Int)(implicitpos:Position):Tree=
83+
BinaryOp(ir.Trees.JSBinaryOp.<<, self,IntLiteral(that))
8084
def>>(that:Tree)(implicitpos:Position):Tree=
8185
BinaryOp(ir.Trees.JSBinaryOp.>>, self, that)
8286
def>>>(that:Tree)(implicitpos:Position):Tree=

‎linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/VarField.scala

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ private[emitter] object VarField {
5858
/** Static fields.*/
5959
finalvalt= mk("$t")
6060

61+
/** Static fields, hi word of a long.*/
62+
finalvalthi= mk("$thi")
63+
6164
/** Scala module accessor.*/
6265
finalvalm= mk("$m")
6366

@@ -123,12 +126,18 @@ private[emitter] object VarField {
123126
/** Local field for class captures.*/
124127
finalvalcc= mk("$cc")
125128

129+
/** Local field for the hi word of a long class capture.*/
130+
finalvalcchi= mk("$cchi")
131+
126132
/** Local field for super class.*/
127133
finalvalsuperClass= mk("$superClass")
128134

129135
/** Local field for this replacement.*/
130136
finalvalthiz= mk("$thiz")
131137

138+
/** Local field for the hi word of a this replacement.*/
139+
finalvalthizhi= mk("$thizhi")
140+
132141
/** Local field for dynamic imports.*/
133142
finalvalmodule= mk("$module")
134143

@@ -143,8 +152,11 @@ private[emitter] object VarField {
143152
/** The TypeData class.*/
144153
finalvalTypeData= mk("$TypeData")
145154

146-
/** Long zero.*/
147-
finalvalL0= mk("$L0")
155+
/** Hi word of a long result.*/
156+
finalvalresHi= mk("$resHi")
157+
158+
/** Setter for resHi (for ES Modules).*/
159+
finalvalsetResHi= mk("$setResHi")
148160

149161
/** DataView for floating point bit manipulation.*/
150162
finalvalfpBitsDataView= mk("$fpBitsDataView")
@@ -167,6 +179,17 @@ private[emitter] object VarField {
167179

168180
finalvalcharAt= mk("$charAt")
169181

182+
// Long
183+
184+
/** The Long class.*/
185+
finalvalLong= mk("$Long")
186+
187+
/** Box long.*/
188+
finalvalbL= mk("$bL")
189+
190+
/** Boxed Long zero.*/
191+
finalvalbL0= mk("$bL0")
192+
170193
// Object helpers
171194

172195
finalvalobjectClone= mk("$objectClone")

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp