Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : *
4 : * Copyright 2015 Mozilla Foundation
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #include "wasm/WasmCompile.h"
20 :
21 : #include "jsprf.h"
22 :
23 : #include "wasm/WasmBinaryIterator.h"
24 : #include "wasm/WasmGenerator.h"
25 : #include "wasm/WasmSignalHandlers.h"
26 : #include "wasm/WasmValidate.h"
27 :
28 : using namespace js;
29 : using namespace js::jit;
30 : using namespace js::wasm;
31 :
32 : static bool
33 0 : DecodeFunctionBody(Decoder& d, ModuleGenerator& mg, uint32_t funcIndex)
34 : {
35 : uint32_t bodySize;
36 0 : if (!d.readVarU32(&bodySize))
37 0 : return d.fail("expected number of function body bytes");
38 :
39 0 : const size_t offsetInModule = d.currentOffset();
40 :
41 : // Skip over the function body; we'll validate it later.
42 : const uint8_t* bodyBegin;
43 0 : if (!d.readBytes(bodySize, &bodyBegin))
44 0 : return d.fail("function body length too big");
45 :
46 0 : FunctionGenerator fg;
47 0 : if (!mg.startFuncDef(offsetInModule, &fg))
48 0 : return false;
49 :
50 0 : if (!fg.bytes().resize(bodySize))
51 0 : return false;
52 :
53 0 : memcpy(fg.bytes().begin(), bodyBegin, bodySize);
54 :
55 0 : return mg.finishFuncDef(funcIndex, &fg);
56 : }
57 :
58 : static bool
59 0 : DecodeCodeSection(Decoder& d, ModuleGenerator& mg)
60 : {
61 : uint32_t sectionStart, sectionSize;
62 0 : if (!d.startSection(SectionId::Code, &mg.mutableEnv(), §ionStart, §ionSize, "code"))
63 0 : return false;
64 :
65 0 : if (!mg.startFuncDefs())
66 0 : return false;
67 :
68 0 : if (sectionStart == Decoder::NotStarted) {
69 0 : if (mg.env().numFuncDefs() != 0)
70 0 : return d.fail("expected function bodies");
71 :
72 0 : return mg.finishFuncDefs();
73 : }
74 :
75 : uint32_t numFuncDefs;
76 0 : if (!d.readVarU32(&numFuncDefs))
77 0 : return d.fail("expected function body count");
78 :
79 0 : if (numFuncDefs != mg.env().numFuncDefs())
80 0 : return d.fail("function body count does not match function signature count");
81 :
82 0 : for (uint32_t funcDefIndex = 0; funcDefIndex < numFuncDefs; funcDefIndex++) {
83 0 : if (!DecodeFunctionBody(d, mg, mg.env().numFuncImports() + funcDefIndex))
84 0 : return false;
85 : }
86 :
87 0 : if (!d.finishSection(sectionStart, sectionSize, "code"))
88 0 : return false;
89 :
90 0 : return mg.finishFuncDefs();
91 : }
92 :
93 : bool
94 0 : CompileArgs::initFromContext(JSContext* cx, ScriptedCaller&& scriptedCaller)
95 : {
96 0 : alwaysBaseline = cx->options().wasmAlwaysBaseline();
97 :
98 : // Debug information such as source view or debug traps will require
99 : // additional memory and permanently stay in baseline code, so we try to
100 : // only enable it when a developer actually cares: when the debugger tab
101 : // is open.
102 0 : debugEnabled = cx->compartment()->debuggerObservesAsmJS();
103 :
104 0 : this->scriptedCaller = Move(scriptedCaller);
105 0 : return assumptions.initBuildIdFromContext(cx);
106 : }
107 :
108 : SharedModule
109 0 : wasm::Compile(const ShareableBytes& bytecode, const CompileArgs& args, UniqueChars* error)
110 : {
111 0 : MOZ_RELEASE_ASSERT(wasm::HaveSignalHandlers());
112 :
113 0 : Decoder d(bytecode.bytes, error);
114 :
115 0 : auto env = js::MakeUnique<ModuleEnvironment>();
116 0 : if (!env)
117 0 : return nullptr;
118 :
119 0 : if (!DecodeModuleEnvironment(d, env.get()))
120 0 : return nullptr;
121 :
122 0 : ModuleGenerator mg(error);
123 0 : if (!mg.init(Move(env), args))
124 0 : return nullptr;
125 :
126 0 : if (!DecodeCodeSection(d, mg))
127 0 : return nullptr;
128 :
129 0 : if (!DecodeModuleTail(d, &mg.mutableEnv()))
130 0 : return nullptr;
131 :
132 0 : MOZ_ASSERT(!*error, "unreported error in decoding");
133 :
134 0 : return mg.finish(bytecode);
135 9 : }
|