wasm native string の実装を目指して
そもそも今はany型で扱っているが、いいのか? anyref じゃなくて BoxedString 型の ref にした方が良い?
CoreWasmLib.genStringLiteral
+ genCreateStringFromData -> これは完全に置き換え必要
data から array.new_data で i16 array 作る
o createStringFromData で JS string を作る o (ref array any) に cache を保存 o emptyString (JS の string "") genTypeDataName
文字列でデータを持っているのでこれも wasm に
FunctionEmitter
BoxedStringRef = ClassRef(BoxedStringClass) これは IR レベルの話しなので別にいいのか
JSGlobalRef で JS string 参照してるけど、どうせJS interop は見えなくなるので良いのだ
genAdapt の case PrimTypeWithRef
code:scala
case _ =>
/* Calls a bX helper. Most of them are of the form
* bX: (x) => x
* at the JavaScript level, but with a primType->anyref Wasm type.
* For example, for IntType, bI has type i32 -> anyref. This
* asks the JS host to turn a primitive i32 into its generic
* representation, which we can store in an anyref.
*/
fb += wa.Call(genFunctionID.box(primType.primRef))
String も CharType や LongTypeと同様に genBox してやる
ここはいらない。他のところで any に変換している?
genApplyWithDispatch
と思ったけど、 labelNotOurObject 以下は
code:scala
if (t.method.name == toStringMethodName) {
// By spec, toString() is special
assert(argsLocals.isEmpty)
fb += wa.Call(genFunctionID.jsValueToString)
genHijackedClassCall(BoxedStringClass) はどうなる?
genLiteral の StringLiteral (getConstantStringInstr)
case String_length =>
case BinaryOp.String_+
genStringConcat
charToString や intToString や longToString など
genWithDispatch (null.toString は null を返す)
一旦 jsValueToString も js value を wasm string に変換するようにしたほうが何かと良いのでは?
genIsInstanceOf の genIsPrimType (StringType)
genUnbox
ref.as_non_null してるが... CharType や LongType みたいな処理が必要なはず
genMatch
matchableLiteral match { case StringLiteral(value) => ...
Preprocessor
Update specialInstanceTypes for ancestors of hijacked classes
code:scala
def addSpecialInstanceTypeOnAllAncestors(jsValueType: Int): Unit =
strictClassAncestors.foreach(previousClassInfos(_).addSpecialInstanceType(jsValueType))
clazz.className match {
case BoxedStringClass =>
addSpecialInstanceTypeOnAllAncestors(JSValueTypeString)
そもそも JSValueTypeString も消えるはずなのでこのあたりは不要になる
SWasmGen
genZeroOf
boxed string を返すように?
genBoxedZeroOf は... これこのままでいいのかな?
genLoadJSFromSpec などは消えるはず
TypeTransformer
transformType for StringType
any でもいいんだけど、boxed string の ref にする?
hr.icon
Hijacked class は?
length と charAt は IR String_charAt とかになるはず?
codePointAt は WASI の場合は else の処理を利用
indexOf
code:scala
@inline
def indexOf(str: String): Int =
thisString.jsIndexOf(str)
@inline
def indexOf(str: String, fromIndex: Int): Int =
thisString.jsIndexOf(str, fromIndex)
intern is 何?
lastIndexOf これを pure scala で
matches うわ〜〜〜 Regex
repeat ES2015 以上を使わない
replace
jsSplit を使わない実装
Regex
split
startsWith
substring
toLowerCase
toUpperCase
くらいか?
hr.icon
code:lisp
(type $v.java.lang.StringBox (sub $v.java.lang.Object (struct (field $nameOffset i32) (field $nameSize i32) (field $nameStringIndex i32) (field $kind i32) (field $specialInstanceTypes i32) (field $strictAncestors (ref null $typeDataArray)) (field $componentType (ref null $typeData)) (field $name (mut anyref)) (field $classOfValue (mut (ref null $c.java.lang.Class))) (field $arrayOf (mut (ref null $v.java.lang.Object))) (field $cloneFunction (ref null $cloneFunctionType)) (field $isJSClassInstance (ref null $isJSClassInstanceFuncType)) (field $reflectiveProxies (ref $reflectiveProxies)) (field $m.java.lang.StringBox.hashCode_I (ref $2)) (field $m.java.lang.StringBox.toString_Ljava.lang.String (ref $3)))))
(type $c.java.lang.StringBox (sub $c.java.lang.Object (struct (field $vtable (ref $v.java.lang.StringBox)) (field $itables (ref null $itables)) (field $f.java.lang.StringBox.value (mut (ref any))))))
hr.icon
一旦 wasm string との共存する形で内部の文字列表現をi16arrayにできたけどいくつか懸念あり
StringType vs BoxedStringType
code:scala
case ClassType(className) if className == BoxedStringClass =>
watpe.RefType.nullable(VarGen.genTypeID.i16Array)
case ClassType(className) => transformClassType(className)
case StringType => watpe.RefType.nullable(VarGen.genTypeID.i16Array)
両方とも i16array に変換してみてるけど、BoxedString も実は Long や Char みたいに DerivedBoxClass で BoxedStringClass 作ってそれで囲ってあげたほうが良い?
それの何が嬉しい? long (i64) や char(i32) は、anyref のサブタイプじゃなかったから boxing したかったわけだけど、(ref (array i16)) は anyref のサブタイプだから問題ない。
とはいえ j.l.Object のサブタイプじゃないから、扱いが面倒になっているところはある...
null
code:scala
// TODO: handle null
// fb += wa.Call(genFunctionID.jsValueToStringForConcat) // for null
null.toString とかやってみると良い?
genAdapt
semantics の維持
toString の実装、これも pure Scala で実装しないといかんのでは...?
Implications for formatting negative values in hexadecimal
まあこの2つか
まああとは String 関連の標準ライブラリを少しずつ Scala 実装に置き換えていって〜