Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/signature.h" | 5 #include "src/signature.h" |
| 6 | 6 |
| 7 #include "src/handles.h" | 7 #include "src/handles.h" |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 #include "src/zone-containers.h" | 9 #include "src/zone-containers.h" |
| 10 | 10 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 if (FLAG_trace_wasm_encoder) PrintF(__VA_ARGS__); \ | 23 if (FLAG_trace_wasm_encoder) PrintF(__VA_ARGS__); \ |
| 24 } while (false) | 24 } while (false) |
| 25 #else | 25 #else |
| 26 #define TRACE(...) | 26 #define TRACE(...) |
| 27 #endif | 27 #endif |
| 28 | 28 |
| 29 namespace v8 { | 29 namespace v8 { |
| 30 namespace internal { | 30 namespace internal { |
| 31 namespace wasm { | 31 namespace wasm { |
| 32 | 32 |
| 33 // Emit a section name and the size as a padded varint that can be patched | 33 // Emit a section code and the size as a padded varint that can be patched |
| 34 // later. | 34 // later. |
| 35 size_t EmitSection(WasmSection::Code code, ZoneBuffer& buffer) { | 35 size_t EmitSection(WasmSectionCode code, ZoneBuffer& buffer) { |
| 36 // Emit the section name. | 36 // Emit the section code. |
| 37 const char* name = WasmSection::getName(code); | 37 buffer.write_u8(code); |
| 38 TRACE("emit section: %s\n", name); | |
| 39 size_t length = WasmSection::getNameLength(code); | |
| 40 buffer.write_size(length); // Section name string size. | |
| 41 buffer.write(reinterpret_cast<const byte*>(name), length); | |
| 42 | 38 |
| 43 // Emit a placeholder for the length. | 39 // Emit a placeholder for the length. |
| 44 return buffer.reserve_u32v(); | 40 return buffer.reserve_u32v(); |
| 45 } | 41 } |
| 46 | 42 |
| 47 // Patch the size of a section after it's finished. | 43 // Patch the size of a section after it's finished. |
| 48 void FixupSection(ZoneBuffer& buffer, size_t start) { | 44 void FixupSection(ZoneBuffer& buffer, size_t start) { |
| 49 buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start - | 45 buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start - |
| 50 kPaddedVarInt32Size)); | 46 kPaddedVarInt32Size)); |
| 51 } | 47 } |
| 52 | 48 |
| 53 WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder) | 49 WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder) |
| 54 : builder_(builder), | 50 : builder_(builder), |
| 55 locals_(builder->zone()), | 51 locals_(builder->zone()), |
| 56 signature_index_(0), | 52 signature_index_(0), |
| 57 exported_(0), | 53 exported_(0), |
| 54 func_index_(static_cast<uint32_t>(builder->imports_.size() + | |
| 55 builder->functions_.size())), | |
| 58 body_(builder->zone()), | 56 body_(builder->zone()), |
| 59 name_(builder->zone()), | 57 name_(builder->zone()), |
| 60 i32_temps_(builder->zone()), | 58 i32_temps_(builder->zone()), |
| 61 i64_temps_(builder->zone()), | 59 i64_temps_(builder->zone()), |
| 62 f32_temps_(builder->zone()), | 60 f32_temps_(builder->zone()), |
| 63 f64_temps_(builder->zone()) {} | 61 f64_temps_(builder->zone()) {} |
| 64 | 62 |
| 65 void WasmFunctionBuilder::EmitVarInt(uint32_t val) { | 63 void WasmFunctionBuilder::EmitVarInt(uint32_t val) { |
| 66 byte buffer[8]; | 64 byte buffer[8]; |
| 67 byte* ptr = buffer; | 65 byte* ptr = buffer; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 83 } | 81 } |
| 84 | 82 |
| 85 void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) { | 83 void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) { |
| 86 EmitWithVarInt(kExprGetLocal, local_index); | 84 EmitWithVarInt(kExprGetLocal, local_index); |
| 87 } | 85 } |
| 88 | 86 |
| 89 void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) { | 87 void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) { |
| 90 EmitWithVarInt(kExprSetLocal, local_index); | 88 EmitWithVarInt(kExprSetLocal, local_index); |
| 91 } | 89 } |
| 92 | 90 |
| 91 void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) { | |
| 92 EmitWithVarInt(kExprTeeLocal, local_index); | |
| 93 } | |
| 94 | |
| 93 void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) { | 95 void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) { |
| 94 for (size_t i = 0; i < code_size; ++i) { | 96 for (size_t i = 0; i < code_size; ++i) { |
| 95 body_.push_back(code[i]); | 97 body_.push_back(code[i]); |
| 96 } | 98 } |
| 97 } | 99 } |
| 98 | 100 |
| 99 void WasmFunctionBuilder::Emit(WasmOpcode opcode) { | 101 void WasmFunctionBuilder::Emit(WasmOpcode opcode) { |
| 100 body_.push_back(static_cast<byte>(opcode)); | 102 body_.push_back(static_cast<byte>(opcode)); |
| 101 } | 103 } |
| 102 | 104 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 for (int i = 0; i < name_length; ++i) { | 138 for (int i = 0; i < name_length; ++i) { |
| 137 name_.push_back(*(name + i)); | 139 name_.push_back(*(name + i)); |
| 138 } | 140 } |
| 139 } | 141 } |
| 140 } | 142 } |
| 141 | 143 |
| 142 void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const { | 144 void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const { |
| 143 buffer.write_u32v(signature_index_); | 145 buffer.write_u32v(signature_index_); |
| 144 } | 146 } |
| 145 | 147 |
| 146 void WasmFunctionBuilder::WriteExport(ZoneBuffer& buffer, | 148 void WasmFunctionBuilder::WriteExport(ZoneBuffer& buffer) const { |
| 147 uint32_t func_index) const { | |
| 148 if (exported_) { | 149 if (exported_) { |
| 149 buffer.write_u32v(func_index); | |
| 150 buffer.write_size(name_.size()); | 150 buffer.write_size(name_.size()); |
| 151 if (name_.size() > 0) { | 151 if (name_.size() > 0) { |
| 152 buffer.write(reinterpret_cast<const byte*>(&name_[0]), name_.size()); | 152 buffer.write(reinterpret_cast<const byte*>(&name_[0]), name_.size()); |
| 153 } | 153 } |
| 154 buffer.write_u8(kExternalFunction); | |
| 155 buffer.write_u32v(func_index_); | |
| 154 } | 156 } |
| 155 } | 157 } |
| 156 | 158 |
| 157 void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const { | 159 void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const { |
| 158 size_t locals_size = locals_.Size(); | 160 size_t locals_size = locals_.Size(); |
| 159 buffer.write_size(locals_size + body_.size()); | 161 buffer.write_size(locals_size + body_.size()); |
| 160 buffer.EnsureSpace(locals_size); | 162 buffer.EnsureSpace(locals_size); |
| 161 byte** ptr = buffer.pos_ptr(); | 163 byte** ptr = buffer.pos_ptr(); |
| 162 locals_.Emit(*ptr); | 164 locals_.Emit(*ptr); |
| 163 (*ptr) += locals_size; // UGLY: manual bump of position pointer | 165 (*ptr) += locals_size; // UGLY: manual bump of position pointer |
| 164 if (body_.size() > 0) { | 166 if (body_.size() > 0) { |
| 165 buffer.write(&body_[0], body_.size()); | 167 buffer.write(&body_[0], body_.size()); |
| 166 } | 168 } |
| 167 } | 169 } |
| 168 | 170 |
| 169 WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data, | 171 WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data, |
| 170 uint32_t size, uint32_t dest) | 172 uint32_t size, uint32_t dest) |
| 171 : data_(zone), dest_(dest) { | 173 : data_(zone), dest_(dest) { |
| 172 for (size_t i = 0; i < size; ++i) { | 174 for (size_t i = 0; i < size; ++i) { |
| 173 data_.push_back(data[i]); | 175 data_.push_back(data[i]); |
| 174 } | 176 } |
| 175 } | 177 } |
| 176 | 178 |
| 177 void WasmDataSegmentEncoder::Write(ZoneBuffer& buffer) const { | 179 void WasmDataSegmentEncoder::Write(ZoneBuffer& buffer) const { |
| 180 buffer.write_u8(0); // linear memory zero | |
| 181 buffer.write_u8(kExprI32Const); | |
| 178 buffer.write_u32v(dest_); | 182 buffer.write_u32v(dest_); |
| 183 buffer.write_u8(kExprEnd); | |
| 179 buffer.write_u32v(static_cast<uint32_t>(data_.size())); | 184 buffer.write_u32v(static_cast<uint32_t>(data_.size())); |
| 180 buffer.write(&data_[0], data_.size()); | 185 buffer.write(&data_[0], data_.size()); |
| 181 } | 186 } |
| 182 | 187 |
| 183 WasmModuleBuilder::WasmModuleBuilder(Zone* zone) | 188 WasmModuleBuilder::WasmModuleBuilder(Zone* zone) |
| 184 : zone_(zone), | 189 : zone_(zone), |
| 185 signatures_(zone), | 190 signatures_(zone), |
| 186 imports_(zone), | 191 imports_(zone), |
| 187 functions_(zone), | 192 functions_(zone), |
| 188 data_segments_(zone), | 193 data_segments_(zone), |
| 189 indirect_functions_(zone), | 194 indirect_functions_(zone), |
| 190 globals_(zone), | 195 globals_(zone), |
| 191 signature_map_(zone), | 196 signature_map_(zone), |
| 192 start_function_index_(-1) {} | 197 start_function_index_(-1) {} |
| 193 | 198 |
| 194 uint32_t WasmModuleBuilder::AddFunction() { | 199 WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) { |
| 195 functions_.push_back(new (zone_) WasmFunctionBuilder(this)); | 200 functions_.push_back(new (zone_) WasmFunctionBuilder(this)); |
| 196 return static_cast<uint32_t>(functions_.size() - 1); | 201 if (sig) functions_.back()->SetSignature(sig); |
|
ahaas
2016/09/16 11:42:18
Could you add a comment about what it means if sig
titzer
2016/09/16 12:23:20
Done.
| |
| 197 } | 202 return functions_.back(); |
| 198 | |
| 199 WasmFunctionBuilder* WasmModuleBuilder::FunctionAt(size_t index) { | |
| 200 if (functions_.size() > index) { | |
| 201 return functions_.at(index); | |
| 202 } else { | |
| 203 return nullptr; | |
| 204 } | |
| 205 } | 203 } |
| 206 | 204 |
| 207 void WasmModuleBuilder::AddDataSegment(WasmDataSegmentEncoder* data) { | 205 void WasmModuleBuilder::AddDataSegment(WasmDataSegmentEncoder* data) { |
| 208 data_segments_.push_back(data); | 206 data_segments_.push_back(data); |
| 209 } | 207 } |
| 210 | 208 |
| 211 bool WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a, | 209 bool WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a, |
| 212 FunctionSig* b) const { | 210 FunctionSig* b) const { |
| 213 if (a->return_count() < b->return_count()) return true; | 211 if (a->return_count() < b->return_count()) return true; |
| 214 if (a->return_count() > b->return_count()) return false; | 212 if (a->return_count() > b->return_count()) return false; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 236 return index; | 234 return index; |
| 237 } | 235 } |
| 238 } | 236 } |
| 239 | 237 |
| 240 void WasmModuleBuilder::AddIndirectFunction(uint32_t index) { | 238 void WasmModuleBuilder::AddIndirectFunction(uint32_t index) { |
| 241 indirect_functions_.push_back(index); | 239 indirect_functions_.push_back(index); |
| 242 } | 240 } |
| 243 | 241 |
| 244 uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length, | 242 uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length, |
| 245 FunctionSig* sig) { | 243 FunctionSig* sig) { |
| 244 DCHECK_EQ(0, functions_.size()); // imports must be added before functions! | |
| 246 imports_.push_back({AddSignature(sig), name, name_length}); | 245 imports_.push_back({AddSignature(sig), name, name_length}); |
| 247 return static_cast<uint32_t>(imports_.size() - 1); | 246 return static_cast<uint32_t>(imports_.size() - 1); |
| 248 } | 247 } |
| 249 | 248 |
| 250 void WasmModuleBuilder::MarkStartFunction(uint32_t index) { | 249 void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) { |
| 251 start_function_index_ = index; | 250 start_function_index_ = function->func_index(); |
| 252 } | 251 } |
| 253 | 252 |
| 254 uint32_t WasmModuleBuilder::AddGlobal(LocalType type, bool exported) { | 253 uint32_t WasmModuleBuilder::AddGlobal(LocalType type, bool exported, |
| 255 globals_.push_back(std::make_pair(type, exported)); | 254 bool mutability) { |
| 255 globals_.push_back(std::make_tuple(type, exported, mutability)); | |
| 256 return static_cast<uint32_t>(globals_.size() - 1); | 256 return static_cast<uint32_t>(globals_.size() - 1); |
| 257 } | 257 } |
| 258 | 258 |
| 259 void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { | 259 void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { |
| 260 uint32_t exports = 0; | 260 uint32_t exports = 0; |
| 261 bool names = false; | |
|
ahaas
2016/09/16 11:42:18
I think it would be better if this variable were d
titzer
2016/09/16 12:23:20
Done.
| |
| 261 | 262 |
| 262 // == Emit magic ============================================================= | 263 // == Emit magic ============================================================= |
| 263 TRACE("emit magic\n"); | 264 TRACE("emit magic\n"); |
| 264 buffer.write_u32(kWasmMagic); | 265 buffer.write_u32(kWasmMagic); |
| 265 buffer.write_u32(kWasmVersion); | 266 buffer.write_u32(kWasmVersion); |
| 266 | 267 |
| 267 // == Emit signatures ======================================================== | 268 // == Emit signatures ======================================================== |
| 268 if (signatures_.size() > 0) { | 269 if (signatures_.size() > 0) { |
| 269 size_t start = EmitSection(WasmSection::Code::Signatures, buffer); | 270 size_t start = EmitSection(kTypeSectionCode, buffer); |
| 270 buffer.write_size(signatures_.size()); | 271 buffer.write_size(signatures_.size()); |
| 271 | 272 |
| 272 for (FunctionSig* sig : signatures_) { | 273 for (FunctionSig* sig : signatures_) { |
| 273 buffer.write_u8(kWasmFunctionTypeForm); | 274 buffer.write_u8(kWasmFunctionTypeForm); |
| 274 buffer.write_size(sig->parameter_count()); | 275 buffer.write_size(sig->parameter_count()); |
| 275 for (size_t j = 0; j < sig->parameter_count(); j++) { | 276 for (size_t j = 0; j < sig->parameter_count(); j++) { |
| 276 buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(sig->GetParam(j))); | 277 buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(sig->GetParam(j))); |
| 277 } | 278 } |
| 278 buffer.write_size(sig->return_count()); | 279 buffer.write_size(sig->return_count()); |
| 279 for (size_t j = 0; j < sig->return_count(); j++) { | 280 for (size_t j = 0; j < sig->return_count(); j++) { |
| 280 buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(sig->GetReturn(j))); | 281 buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(sig->GetReturn(j))); |
| 281 } | 282 } |
| 282 } | 283 } |
| 283 FixupSection(buffer, start); | 284 FixupSection(buffer, start); |
| 284 } | 285 } |
| 285 | 286 |
| 286 // == Emit globals =========================================================== | |
| 287 if (globals_.size() > 0) { | |
| 288 size_t start = EmitSection(WasmSection::Code::Globals, buffer); | |
| 289 buffer.write_size(globals_.size()); | |
| 290 | |
| 291 for (auto global : globals_) { | |
| 292 buffer.write_u32v(0); // Length of the global name. | |
| 293 buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(global.first)); | |
| 294 buffer.write_u8(global.second); | |
| 295 } | |
| 296 FixupSection(buffer, start); | |
| 297 } | |
| 298 | |
| 299 // == Emit imports =========================================================== | 287 // == Emit imports =========================================================== |
| 300 if (imports_.size() > 0) { | 288 if (imports_.size() > 0) { |
| 301 size_t start = EmitSection(WasmSection::Code::ImportTable, buffer); | 289 size_t start = EmitSection(kImportSectionCode, buffer); |
| 302 buffer.write_size(imports_.size()); | 290 buffer.write_size(imports_.size()); |
| 303 for (auto import : imports_) { | 291 for (auto import : imports_) { |
| 292 buffer.write_u32v(import.name_length); // module name length | |
|
ahaas
2016/09/16 11:42:18
Are these comments really consistent with the code
titzer
2016/09/16 12:23:20
Done.
| |
| 293 buffer.write(reinterpret_cast<const byte*>(import.name), // module name | |
| 294 import.name_length); | |
| 295 buffer.write_u32v(0); // import name length | |
| 296 buffer.write_u8(kExternalFunction); | |
| 304 buffer.write_u32v(import.sig_index); | 297 buffer.write_u32v(import.sig_index); |
| 305 buffer.write_u32v(import.name_length); | |
| 306 buffer.write(reinterpret_cast<const byte*>(import.name), | |
| 307 import.name_length); | |
| 308 buffer.write_u32v(0); | |
| 309 } | 298 } |
| 310 FixupSection(buffer, start); | 299 FixupSection(buffer, start); |
| 311 } | 300 } |
| 312 | 301 |
| 313 // == Emit function signatures =============================================== | 302 // == Emit function signatures =============================================== |
| 314 if (functions_.size() > 0) { | 303 if (functions_.size() > 0) { |
| 315 size_t start = EmitSection(WasmSection::Code::FunctionSignatures, buffer); | 304 size_t start = EmitSection(kFunctionSectionCode, buffer); |
| 316 buffer.write_size(functions_.size()); | 305 buffer.write_size(functions_.size()); |
| 317 for (auto function : functions_) { | 306 for (auto function : functions_) { |
| 318 function->WriteSignature(buffer); | 307 function->WriteSignature(buffer); |
| 319 if (function->exported()) exports++; | 308 if (function->exported()) exports++; |
| 309 if (function->name_.size() > 0) names = true; | |
| 320 } | 310 } |
| 321 FixupSection(buffer, start); | 311 FixupSection(buffer, start); |
| 322 } | 312 } |
| 323 | 313 |
| 324 // == emit function table ==================================================== | 314 // == emit function table ==================================================== |
| 325 if (indirect_functions_.size() > 0) { | 315 if (indirect_functions_.size() > 0) { |
| 326 size_t start = EmitSection(WasmSection::Code::FunctionTable, buffer); | 316 size_t start = EmitSection(kTableSectionCode, buffer); |
| 317 buffer.write_u8(1); // table count | |
| 318 buffer.write_u8(kWasmAnyFunctionTypeForm); | |
| 319 buffer.write_u8(kResizableMaximumFlag); | |
| 327 buffer.write_size(indirect_functions_.size()); | 320 buffer.write_size(indirect_functions_.size()); |
| 328 | 321 buffer.write_size(indirect_functions_.size()); |
| 329 for (auto index : indirect_functions_) { | |
| 330 buffer.write_u32v(index); | |
| 331 } | |
| 332 FixupSection(buffer, start); | 322 FixupSection(buffer, start); |
| 333 } | 323 } |
| 334 | 324 |
| 335 // == emit memory declaration ================================================ | 325 // == emit memory declaration ================================================ |
| 336 { | 326 { |
| 337 size_t start = EmitSection(WasmSection::Code::Memory, buffer); | 327 size_t start = EmitSection(kMemorySectionCode, buffer); |
| 328 buffer.write_u8(1); // memory count | |
| 329 buffer.write_u32v(kResizableMaximumFlag); | |
| 338 buffer.write_u32v(16); // min memory size | 330 buffer.write_u32v(16); // min memory size |
| 339 buffer.write_u32v(16); // max memory size | 331 buffer.write_u32v(16); // max memory size |
| 340 buffer.write_u8(0); // memory export | 332 FixupSection(buffer, start); |
| 341 static_assert(kDeclMemorySize == 3, "memory size must match emit above"); | 333 } |
| 334 | |
| 335 // == Emit globals =========================================================== | |
| 336 if (globals_.size() > 0) { | |
| 337 size_t start = EmitSection(kGlobalSectionCode, buffer); | |
| 338 buffer.write_size(globals_.size()); | |
| 339 | |
| 340 for (auto global : globals_) { | |
|
ahaas
2016/09/16 11:42:18
I think auto makes code harder to read. Would it b
titzer
2016/09/16 12:23:20
All the loops here are doing that. It's a matter o
ahaas
2016/09/16 13:32:51
Could you add a comment which says that global is
| |
| 341 buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(std::get<0>(global))); | |
|
ahaas
2016/09/16 11:42:18
Define a constant instead of using 0 here.
titzer
2016/09/16 12:23:20
Done.
| |
| 342 buffer.write_u8(std::get<2>(global)); | |
|
ahaas
2016/09/16 11:42:18
same here
titzer
2016/09/16 12:23:20
Done.
| |
| 343 switch (std::get<0>(global)) { | |
|
ahaas
2016/09/16 11:42:18
same here.
titzer
2016/09/16 12:23:20
Done.
| |
| 344 case kAstI32: { | |
| 345 static const byte code[] = {WASM_I32V_1(0)}; | |
| 346 buffer.write(code, sizeof(code)); | |
| 347 break; | |
| 348 } | |
| 349 case kAstF32: { | |
| 350 static const byte code[] = {WASM_F32(0)}; | |
| 351 buffer.write(code, sizeof(code)); | |
| 352 break; | |
| 353 } | |
| 354 case kAstI64: { | |
| 355 static const byte code[] = {WASM_I64V_1(0)}; | |
| 356 buffer.write(code, sizeof(code)); | |
| 357 break; | |
| 358 } | |
| 359 case kAstF64: { | |
| 360 static const byte code[] = {WASM_F64(0.0)}; | |
| 361 buffer.write(code, sizeof(code)); | |
| 362 break; | |
| 363 } | |
| 364 default: | |
| 365 UNREACHABLE(); | |
| 366 } | |
| 367 buffer.write_u8(kExprEnd); | |
| 368 } | |
| 342 FixupSection(buffer, start); | 369 FixupSection(buffer, start); |
| 343 } | 370 } |
| 344 | 371 |
| 345 // == emit exports =========================================================== | 372 // == emit exports =========================================================== |
| 346 if (exports > 0) { | 373 if (exports > 0) { |
| 347 size_t start = EmitSection(WasmSection::Code::ExportTable, buffer); | 374 size_t start = EmitSection(kExportSectionCode, buffer); |
| 348 buffer.write_u32v(exports); | 375 buffer.write_u32v(exports); |
| 349 uint32_t index = 0; | 376 for (auto function : functions_) function->WriteExport(buffer); |
| 350 for (auto function : functions_) { | |
| 351 function->WriteExport(buffer, index++); | |
| 352 } | |
| 353 FixupSection(buffer, start); | 377 FixupSection(buffer, start); |
| 354 } | 378 } |
| 355 | 379 |
| 356 // == emit start function index ============================================== | 380 // == emit start function index ============================================== |
| 357 if (start_function_index_ >= 0) { | 381 if (start_function_index_ >= 0) { |
| 358 size_t start = EmitSection(WasmSection::Code::StartFunction, buffer); | 382 size_t start = EmitSection(kStartSectionCode, buffer); |
| 359 buffer.write_u32v(start_function_index_); | 383 buffer.write_u32v(start_function_index_); |
| 360 FixupSection(buffer, start); | 384 FixupSection(buffer, start); |
| 361 } | 385 } |
| 362 | 386 |
| 387 // == emit function table elements =========================================== | |
| 388 if (indirect_functions_.size() > 0) { | |
| 389 size_t start = EmitSection(kElementSectionCode, buffer); | |
| 390 buffer.write_u8(1); // count of entries | |
| 391 buffer.write_u8(0); // table index | |
| 392 buffer.write_u8(kExprI32Const); // offset | |
| 393 buffer.write_u32v(0); | |
| 394 buffer.write_u8(kExprEnd); | |
| 395 buffer.write_size(indirect_functions_.size()); // element count | |
| 396 | |
| 397 for (auto index : indirect_functions_) { | |
| 398 buffer.write_u32v(index); | |
| 399 } | |
| 400 | |
| 401 FixupSection(buffer, start); | |
| 402 } | |
| 403 | |
| 363 // == emit code ============================================================== | 404 // == emit code ============================================================== |
| 364 if (functions_.size() > 0) { | 405 if (functions_.size() > 0) { |
| 365 size_t start = EmitSection(WasmSection::Code::FunctionBodies, buffer); | 406 size_t start = EmitSection(kCodeSectionCode, buffer); |
| 366 buffer.write_size(functions_.size()); | 407 buffer.write_size(functions_.size()); |
| 367 for (auto function : functions_) { | 408 for (auto function : functions_) { |
| 368 function->WriteBody(buffer); | 409 function->WriteBody(buffer); |
| 369 } | 410 } |
| 370 FixupSection(buffer, start); | 411 FixupSection(buffer, start); |
| 371 } | 412 } |
| 372 | 413 |
| 373 // == emit data segments ===================================================== | 414 // == emit data segments ===================================================== |
| 374 if (data_segments_.size() > 0) { | 415 if (data_segments_.size() > 0) { |
| 375 size_t start = EmitSection(WasmSection::Code::DataSegments, buffer); | 416 size_t start = EmitSection(kDataSectionCode, buffer); |
| 376 buffer.write_size(data_segments_.size()); | 417 buffer.write_size(data_segments_.size()); |
| 377 | 418 |
| 378 for (auto segment : data_segments_) { | 419 for (auto segment : data_segments_) { |
| 379 segment->Write(buffer); | 420 segment->Write(buffer); |
| 380 } | 421 } |
| 381 FixupSection(buffer, start); | 422 FixupSection(buffer, start); |
| 382 } | 423 } |
| 424 | |
| 425 // == Emit names ============================================================= | |
| 426 if (names) { | |
| 427 // Emit the section code. | |
| 428 buffer.write_u8(kUnknownSectionCode); | |
| 429 // Emit the section string. | |
| 430 buffer.write_size(4); | |
| 431 buffer.write(reinterpret_cast<const byte*>("name"), 4); | |
| 432 // Emit a placeholder for the length. | |
| 433 size_t start = buffer.reserve_u32v(); | |
| 434 // Emit the names. | |
| 435 buffer.write_size(functions_.size()); | |
| 436 for (auto function : functions_) { | |
| 437 buffer.write_size(function->name_.size()); | |
| 438 if (function->name_.size() > 0) { | |
| 439 buffer.write(reinterpret_cast<const byte*>(&function->name_[0]), | |
| 440 function->name_.size()); | |
| 441 } | |
| 442 buffer.write_u8(0); | |
| 443 } | |
| 444 FixupSection(buffer, start); | |
| 445 } | |
| 383 } | 446 } |
| 384 } // namespace wasm | 447 } // namespace wasm |
| 385 } // namespace internal | 448 } // namespace internal |
| 386 } // namespace v8 | 449 } // namespace v8 |
| OLD | NEW |