|
| 1 | +// Copyright 2024 the V8 project authors. All rights reserved. |
| 2 | +// Use of this source code is governed by a BSD-style license that can be |
| 3 | +// found in the LICENSE file. |
| 4 | +// |
| 5 | +// Flags: --allow-natives-syntax |
| 6 | + |
| 7 | +varkWasmH0=0; |
| 8 | +varkWasmH1=0x61; |
| 9 | +varkWasmH2=0x73; |
| 10 | +varkWasmH3=0x6d; |
| 11 | +varkWasmV0=0x1; |
| 12 | +varkWasmV1=0; |
| 13 | +varkWasmV2=0; |
| 14 | +varkWasmV3=0; |
| 15 | +letkTypeSectionCode=1;// Function signature declarations |
| 16 | +letkFunctionSectionCode=3;// Function declarations |
| 17 | +letkExportSectionCode=7;// Exports |
| 18 | +letkCodeSectionCode=10;// Function code |
| 19 | +letkWasmFunctionTypeForm=0x60; |
| 20 | +letkWasmStructTypeForm=0x5f; |
| 21 | +letkNoSuperType=0xFFFFFFFF; |
| 22 | +letkWasmI32=0x7f; |
| 23 | +letkWasmExternRef=-0x11; |
| 24 | +letkLeb128Mask=0x7f; |
| 25 | +letkExternalFunction=0; |
| 26 | +functionmakeSig(params,results){ |
| 27 | +return{params: params,results: results}; |
| 28 | +} |
| 29 | +constkWasmOpcodes={ |
| 30 | +'End': 0x0b, |
| 31 | +'I32Const': 0x41, |
| 32 | +}; |
| 33 | +functiondefineWasmOpcode(name,value){ |
| 34 | +Object.defineProperty(globalThis,name,{value: value}); |
| 35 | +} |
| 36 | +for(letnameinkWasmOpcodes){ |
| 37 | +defineWasmOpcode(`kExpr${name}`,kWasmOpcodes[name]); |
| 38 | +} |
| 39 | +constkPrefixOpcodes={ |
| 40 | +'GC': 0xfb, |
| 41 | +}; |
| 42 | +for(letprefixinkPrefixOpcodes){ |
| 43 | +defineWasmOpcode(`k${prefix}Prefix`,kPrefixOpcodes[prefix]); |
| 44 | +} |
| 45 | +letkExprStructNew=0x00; |
| 46 | +letkExprExternConvertAny=0x1b; |
| 47 | +classBinary{ |
| 48 | +constructor(){ |
| 49 | +this.length=0; |
| 50 | +this.buffer=newUint8Array(8192); |
| 51 | +} |
| 52 | +trunc_buffer(){ |
| 53 | +returnnewUint8Array(this.buffer.buffer,0,this.length); |
| 54 | +} |
| 55 | +emit_u8(val){ |
| 56 | +this.buffer[this.length++]=val; |
| 57 | +} |
| 58 | +emit_leb_u(val){ |
| 59 | +letv=val&0xff; |
| 60 | +this.buffer[this.length++]=v; |
| 61 | +} |
| 62 | +emit_u32v(val){ |
| 63 | +this.emit_leb_u(val); |
| 64 | +} |
| 65 | +emit_bytes(data){ |
| 66 | +this.buffer.set(data,this.length); |
| 67 | +this.length+=data.length; |
| 68 | +} |
| 69 | +emit_string(string){ |
| 70 | +letstring_utf8=string; |
| 71 | +this.emit_u32v(string_utf8.length); |
| 72 | +for(leti=0;i<string_utf8.length;i++){ |
| 73 | +this.emit_u8(string_utf8.charCodeAt(i)); |
| 74 | +} |
| 75 | +} |
| 76 | +emit_type(type){ |
| 77 | +this.emit_u8(type>=0 ? type : type&kLeb128Mask); |
| 78 | +} |
| 79 | +emit_header(){ |
| 80 | +this.emit_bytes([ |
| 81 | +kWasmH0,kWasmH1,kWasmH2,kWasmH3,kWasmV0,kWasmV1,kWasmV2,kWasmV3 |
| 82 | +]); |
| 83 | +} |
| 84 | +emit_section(section_code,content_generator){ |
| 85 | +this.emit_u8(section_code); |
| 86 | +constsection=newBinary; |
| 87 | +content_generator(section); |
| 88 | +this.emit_u32v(section.length); |
| 89 | +this.emit_bytes(section.trunc_buffer()); |
| 90 | +} |
| 91 | +} |
| 92 | +classWasmFunctionBuilder{ |
| 93 | +constructor(module,name,type_index,arg_names){ |
| 94 | +this.module=module; |
| 95 | +this.name=name; |
| 96 | +this.type_index=type_index; |
| 97 | +} |
| 98 | +exportAs(name){ |
| 99 | +this.module.addExport(name,this.index); |
| 100 | +} |
| 101 | +exportFunc(){ |
| 102 | +this.exportAs(this.name); |
| 103 | +returnthis; |
| 104 | +} |
| 105 | +addBody(body){ |
| 106 | +this.body=body.concat([kExprEnd]); |
| 107 | +} |
| 108 | +} |
| 109 | +functionmakeField(type,mutability){ |
| 110 | +return{type: type,mutability: mutability}; |
| 111 | +} |
| 112 | +classWasmStruct{ |
| 113 | +constructor(fields){ |
| 114 | +this.fields=fields; |
| 115 | +} |
| 116 | +} |
| 117 | +classWasmModuleBuilder{ |
| 118 | +constructor(){ |
| 119 | +this.types=[]; |
| 120 | +this.exports=[]; |
| 121 | +this.functions=[]; |
| 122 | +} |
| 123 | +addType(type,supertype_idx=kNoSuperType,is_final=true, |
| 124 | +is_shared=false){ |
| 125 | +vartype_copy={params: type.params,results: type.results, |
| 126 | +is_final: is_final,is_shared: is_shared, |
| 127 | +supertype: supertype_idx}; |
| 128 | +this.types.push(type_copy); |
| 129 | +returnthis.types.length-1; |
| 130 | +} |
| 131 | +addStruct(fields=kNoSuperType=false,is_shared=false){ |
| 132 | +this.types.push(newWasmStruct(fields)); |
| 133 | +} |
| 134 | +addFunction(name,type,arg_names){ |
| 135 | +lettype_index=typeoftype=='number' ? type : this.addType(type); |
| 136 | +letfunc=newWasmFunctionBuilder(this,name,type_index); |
| 137 | +this.functions.push(func); |
| 138 | +returnfunc; |
| 139 | +} |
| 140 | +addExport(name,index){ |
| 141 | +this.exports.push({name: name,kind: kExternalFunction,index: index}); |
| 142 | +} |
| 143 | +toBuffer(){ |
| 144 | +letbinary=newBinary; |
| 145 | +letwasm=this; |
| 146 | +binary.emit_header(); |
| 147 | +binary.emit_section(kTypeSectionCode,section=>{ |
| 148 | +letlength_with_groups=wasm.types.length; |
| 149 | +section.emit_u32v(length_with_groups); |
| 150 | +for(leti=0;i<wasm.types.length;i++){ |
| 151 | +lettype=wasm.types[i]; |
| 152 | +if(typeinstanceofWasmStruct){ |
| 153 | +section.emit_u8(kWasmStructTypeForm); |
| 154 | +section.emit_u32v(type.fields.length); |
| 155 | +for(letfieldoftype.fields){ |
| 156 | +section.emit_type(field.type); |
| 157 | +section.emit_u8(); |
| 158 | +} |
| 159 | +}else{ |
| 160 | +section.emit_u8(kWasmFunctionTypeForm); |
| 161 | +section.emit_u32v(); |
| 162 | +section.emit_u32v(type.results.length); |
| 163 | +for(letresultoftype.results){ |
| 164 | +section.emit_type(result); |
| 165 | +} |
| 166 | +} |
| 167 | +} |
| 168 | +}); |
| 169 | +binary.emit_section(kFunctionSectionCode,section=>{ |
| 170 | +section.emit_u32v(wasm.functions.length); |
| 171 | +for(letfuncofwasm.functions){ |
| 172 | +section.emit_u32v(func.type_index); |
| 173 | +} |
| 174 | +}); |
| 175 | +varexports_count=wasm.exports.length; |
| 176 | +binary.emit_section(kExportSectionCode,section=>{ |
| 177 | +section.emit_u32v(exports_count); |
| 178 | +for(letexpofwasm.exports){ |
| 179 | +section.emit_string(exp.name); |
| 180 | +section.emit_u8(); |
| 181 | +section.emit_u32v(); |
| 182 | +} |
| 183 | +}); |
| 184 | +binary.emit_section(kCodeSectionCode,section=>{ |
| 185 | +section.emit_u32v(wasm.functions.length); |
| 186 | +for(letfuncofwasm.functions){ |
| 187 | +section.emit_u32v(func.body.length+1); |
| 188 | +section.emit_u8();// 0 locals. |
| 189 | +section.emit_bytes(func.body); |
| 190 | +} |
| 191 | +}); |
| 192 | +returnbinary.trunc_buffer(); |
| 193 | +} |
| 194 | +instantiate(){ |
| 195 | +letmodule=this.toModule(); |
| 196 | +letinstance=newWebAssembly.Instance(module); |
| 197 | +returninstance; |
| 198 | +} |
| 199 | +toModule(){ |
| 200 | +returnnewWebAssembly.Module(this.toBuffer()); |
| 201 | +} |
| 202 | +} |
| 203 | +letbuilder=newWasmModuleBuilder(); |
| 204 | +letstruct_type=builder.addStruct([makeField(kWasmI32)]); |
| 205 | +builder.addFunction('MakeStruct',makeSig([],[kWasmExternRef])).exportFunc() |
| 206 | +.addBody([kExprI32Const,42,kGCPrefix,kExprStructNew,struct_type, |
| 207 | +kGCPrefix,kExprExternConvertAny]); |
| 208 | +letinstance=builder.instantiate(); |
| 209 | +letevil_wasm_object=instance.exports.MakeStruct(); |
| 210 | +functionevil_ctor(){ |
| 211 | +} |
| 212 | +functionevil_cast_jit(evil_o){ |
| 213 | +global_collect_node_info=evil_o;// get nodeinfo from PropertyCellStore |
| 214 | +returnevil_oinstanceofevil_ctor; |
| 215 | +} |
| 216 | +evil_ctor.prototype=evil_wasm_object; |
| 217 | +%PrepareFunctionForOptimization(evil_cast_jit); |
| 218 | +evil_cast_jit(newevil_ctor()); |
| 219 | +evil_cast_jit(newevil_ctor()); |
| 220 | +%OptimizeFunctionOnNextCall(evil_cast_jit); |
| 221 | +evil_cast_jit(); |
0 commit comments