| 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/zone-containers.h" | 9 #include "src/zone/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 // Add the signature if one was provided here. |
| 197 } | 202 if (sig) functions_.back()->SetSignature(sig); |
| 198 | 203 return functions_.back(); |
| 199 WasmFunctionBuilder* WasmModuleBuilder::FunctionAt(size_t index) { | |
| 200 if (functions_.size() > index) { | |
| 201 return functions_.at(index); | |
| 202 } else { | |
| 203 return nullptr; | |
| 204 } | |
| 205 } | 204 } |
| 206 | 205 |
| 207 void WasmModuleBuilder::AddDataSegment(WasmDataSegmentEncoder* data) { | 206 void WasmModuleBuilder::AddDataSegment(WasmDataSegmentEncoder* data) { |
| 208 data_segments_.push_back(data); | 207 data_segments_.push_back(data); |
| 209 } | 208 } |
| 210 | 209 |
| 211 bool WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a, | 210 bool WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a, |
| 212 FunctionSig* b) const { | 211 FunctionSig* b) const { |
| 213 if (a->return_count() < b->return_count()) return true; | 212 if (a->return_count() < b->return_count()) return true; |
| 214 if (a->return_count() > b->return_count()) return false; | 213 if (a->return_count() > b->return_count()) return false; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 236 return index; | 235 return index; |
| 237 } | 236 } |
| 238 } | 237 } |
| 239 | 238 |
| 240 void WasmModuleBuilder::AddIndirectFunction(uint32_t index) { | 239 void WasmModuleBuilder::AddIndirectFunction(uint32_t index) { |
| 241 indirect_functions_.push_back(index); | 240 indirect_functions_.push_back(index); |
| 242 } | 241 } |
| 243 | 242 |
| 244 uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length, | 243 uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length, |
| 245 FunctionSig* sig) { | 244 FunctionSig* sig) { |
| 245 DCHECK_EQ(0, functions_.size()); // imports must be added before functions! |
| 246 imports_.push_back({AddSignature(sig), name, name_length}); | 246 imports_.push_back({AddSignature(sig), name, name_length}); |
| 247 return static_cast<uint32_t>(imports_.size() - 1); | 247 return static_cast<uint32_t>(imports_.size() - 1); |
| 248 } | 248 } |
| 249 | 249 |
| 250 void WasmModuleBuilder::MarkStartFunction(uint32_t index) { | 250 void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) { |
| 251 start_function_index_ = index; | 251 start_function_index_ = function->func_index(); |
| 252 } | 252 } |
| 253 | 253 |
| 254 uint32_t WasmModuleBuilder::AddGlobal(LocalType type, bool exported) { | 254 uint32_t WasmModuleBuilder::AddGlobal(LocalType type, bool exported, |
| 255 globals_.push_back(std::make_pair(type, exported)); | 255 bool mutability) { |
| 256 globals_.push_back(std::make_tuple(type, exported, mutability)); |
| 256 return static_cast<uint32_t>(globals_.size() - 1); | 257 return static_cast<uint32_t>(globals_.size() - 1); |
| 257 } | 258 } |
| 258 | 259 |
| 259 void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { | 260 void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { |
| 260 uint32_t exports = 0; | 261 uint32_t exports = 0; |
| 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 |
| 293 buffer.write(reinterpret_cast<const byte*>(import.name), // module name |
| 294 import.name_length); |
| 295 buffer.write_u32v(0); // field 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 =============================================== |
| 303 bool has_names = false; |
| 314 if (functions_.size() > 0) { | 304 if (functions_.size() > 0) { |
| 315 size_t start = EmitSection(WasmSection::Code::FunctionSignatures, buffer); | 305 size_t start = EmitSection(kFunctionSectionCode, buffer); |
| 316 buffer.write_size(functions_.size()); | 306 buffer.write_size(functions_.size()); |
| 317 for (auto function : functions_) { | 307 for (auto function : functions_) { |
| 318 function->WriteSignature(buffer); | 308 function->WriteSignature(buffer); |
| 319 if (function->exported()) exports++; | 309 if (function->exported()) exports++; |
| 310 if (function->name_.size() > 0) has_names = true; |
| 320 } | 311 } |
| 321 FixupSection(buffer, start); | 312 FixupSection(buffer, start); |
| 322 } | 313 } |
| 323 | 314 |
| 324 // == emit function table ==================================================== | 315 // == emit function table ==================================================== |
| 325 if (indirect_functions_.size() > 0) { | 316 if (indirect_functions_.size() > 0) { |
| 326 size_t start = EmitSection(WasmSection::Code::FunctionTable, buffer); | 317 size_t start = EmitSection(kTableSectionCode, buffer); |
| 318 buffer.write_u8(1); // table count |
| 319 buffer.write_u8(kWasmAnyFunctionTypeForm); |
| 320 buffer.write_u8(kResizableMaximumFlag); |
| 327 buffer.write_size(indirect_functions_.size()); | 321 buffer.write_size(indirect_functions_.size()); |
| 328 | 322 buffer.write_size(indirect_functions_.size()); |
| 329 for (auto index : indirect_functions_) { | |
| 330 buffer.write_u32v(index); | |
| 331 } | |
| 332 FixupSection(buffer, start); | 323 FixupSection(buffer, start); |
| 333 } | 324 } |
| 334 | 325 |
| 335 // == emit memory declaration ================================================ | 326 // == emit memory declaration ================================================ |
| 336 { | 327 { |
| 337 size_t start = EmitSection(WasmSection::Code::Memory, buffer); | 328 size_t start = EmitSection(kMemorySectionCode, buffer); |
| 329 buffer.write_u8(1); // memory count |
| 330 buffer.write_u32v(kResizableMaximumFlag); |
| 338 buffer.write_u32v(16); // min memory size | 331 buffer.write_u32v(16); // min memory size |
| 339 buffer.write_u32v(16); // max memory size | 332 buffer.write_u32v(16); // max memory size |
| 340 buffer.write_u8(0); // memory export | 333 FixupSection(buffer, start); |
| 341 static_assert(kDeclMemorySize == 3, "memory size must match emit above"); | 334 } |
| 335 |
| 336 // == Emit globals =========================================================== |
| 337 if (globals_.size() > 0) { |
| 338 size_t start = EmitSection(kGlobalSectionCode, buffer); |
| 339 buffer.write_size(globals_.size()); |
| 340 |
| 341 for (auto global : globals_) { |
| 342 static const int kLocalTypeIndex = 0; |
| 343 static const int kMutabilityIndex = 2; |
| 344 buffer.write_u8( |
| 345 WasmOpcodes::LocalTypeCodeFor(std::get<kLocalTypeIndex>(global))); |
| 346 buffer.write_u8(std::get<kMutabilityIndex>(global)); |
| 347 switch (std::get<kLocalTypeIndex>(global)) { |
| 348 case kAstI32: { |
| 349 static const byte code[] = {WASM_I32V_1(0)}; |
| 350 buffer.write(code, sizeof(code)); |
| 351 break; |
| 352 } |
| 353 case kAstF32: { |
| 354 static const byte code[] = {WASM_F32(0)}; |
| 355 buffer.write(code, sizeof(code)); |
| 356 break; |
| 357 } |
| 358 case kAstI64: { |
| 359 static const byte code[] = {WASM_I64V_1(0)}; |
| 360 buffer.write(code, sizeof(code)); |
| 361 break; |
| 362 } |
| 363 case kAstF64: { |
| 364 static const byte code[] = {WASM_F64(0.0)}; |
| 365 buffer.write(code, sizeof(code)); |
| 366 break; |
| 367 } |
| 368 default: |
| 369 UNREACHABLE(); |
| 370 } |
| 371 buffer.write_u8(kExprEnd); |
| 372 } |
| 342 FixupSection(buffer, start); | 373 FixupSection(buffer, start); |
| 343 } | 374 } |
| 344 | 375 |
| 345 // == emit exports =========================================================== | 376 // == emit exports =========================================================== |
| 346 if (exports > 0) { | 377 if (exports > 0) { |
| 347 size_t start = EmitSection(WasmSection::Code::ExportTable, buffer); | 378 size_t start = EmitSection(kExportSectionCode, buffer); |
| 348 buffer.write_u32v(exports); | 379 buffer.write_u32v(exports); |
| 349 uint32_t index = 0; | 380 for (auto function : functions_) function->WriteExport(buffer); |
| 350 for (auto function : functions_) { | |
| 351 function->WriteExport(buffer, index++); | |
| 352 } | |
| 353 FixupSection(buffer, start); | 381 FixupSection(buffer, start); |
| 354 } | 382 } |
| 355 | 383 |
| 356 // == emit start function index ============================================== | 384 // == emit start function index ============================================== |
| 357 if (start_function_index_ >= 0) { | 385 if (start_function_index_ >= 0) { |
| 358 size_t start = EmitSection(WasmSection::Code::StartFunction, buffer); | 386 size_t start = EmitSection(kStartSectionCode, buffer); |
| 359 buffer.write_u32v(start_function_index_); | 387 buffer.write_u32v(start_function_index_); |
| 360 FixupSection(buffer, start); | 388 FixupSection(buffer, start); |
| 361 } | 389 } |
| 362 | 390 |
| 391 // == emit function table elements =========================================== |
| 392 if (indirect_functions_.size() > 0) { |
| 393 size_t start = EmitSection(kElementSectionCode, buffer); |
| 394 buffer.write_u8(1); // count of entries |
| 395 buffer.write_u8(0); // table index |
| 396 buffer.write_u8(kExprI32Const); // offset |
| 397 buffer.write_u32v(0); |
| 398 buffer.write_u8(kExprEnd); |
| 399 buffer.write_size(indirect_functions_.size()); // element count |
| 400 |
| 401 for (auto index : indirect_functions_) { |
| 402 buffer.write_u32v(index); |
| 403 } |
| 404 |
| 405 FixupSection(buffer, start); |
| 406 } |
| 407 |
| 363 // == emit code ============================================================== | 408 // == emit code ============================================================== |
| 364 if (functions_.size() > 0) { | 409 if (functions_.size() > 0) { |
| 365 size_t start = EmitSection(WasmSection::Code::FunctionBodies, buffer); | 410 size_t start = EmitSection(kCodeSectionCode, buffer); |
| 366 buffer.write_size(functions_.size()); | 411 buffer.write_size(functions_.size()); |
| 367 for (auto function : functions_) { | 412 for (auto function : functions_) { |
| 368 function->WriteBody(buffer); | 413 function->WriteBody(buffer); |
| 369 } | 414 } |
| 370 FixupSection(buffer, start); | 415 FixupSection(buffer, start); |
| 371 } | 416 } |
| 372 | 417 |
| 373 // == emit data segments ===================================================== | 418 // == emit data segments ===================================================== |
| 374 if (data_segments_.size() > 0) { | 419 if (data_segments_.size() > 0) { |
| 375 size_t start = EmitSection(WasmSection::Code::DataSegments, buffer); | 420 size_t start = EmitSection(kDataSectionCode, buffer); |
| 376 buffer.write_size(data_segments_.size()); | 421 buffer.write_size(data_segments_.size()); |
| 377 | 422 |
| 378 for (auto segment : data_segments_) { | 423 for (auto segment : data_segments_) { |
| 379 segment->Write(buffer); | 424 segment->Write(buffer); |
| 380 } | 425 } |
| 381 FixupSection(buffer, start); | 426 FixupSection(buffer, start); |
| 382 } | 427 } |
| 428 |
| 429 // == Emit names ============================================================= |
| 430 if (has_names) { |
| 431 // Emit the section code. |
| 432 buffer.write_u8(kUnknownSectionCode); |
| 433 // Emit a placeholder for the length. |
| 434 size_t start = buffer.reserve_u32v(); |
| 435 // Emit the section string. |
| 436 buffer.write_size(4); |
| 437 buffer.write(reinterpret_cast<const byte*>("name"), 4); |
| 438 // Emit the names. |
| 439 buffer.write_size(functions_.size()); |
| 440 for (auto function : functions_) { |
| 441 buffer.write_size(function->name_.size()); |
| 442 if (function->name_.size() > 0) { |
| 443 buffer.write(reinterpret_cast<const byte*>(&function->name_[0]), |
| 444 function->name_.size()); |
| 445 } |
| 446 buffer.write_u8(0); |
| 447 } |
| 448 FixupSection(buffer, start); |
| 449 } |
| 383 } | 450 } |
| 384 } // namespace wasm | 451 } // namespace wasm |
| 385 } // namespace internal | 452 } // namespace internal |
| 386 } // namespace v8 | 453 } // namespace v8 |
| OLD | NEW |