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/compiler/wasm-compiler.h" | 5 #include "src/compiler/wasm-compiler.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/isolate-inl.h" | 9 #include "src/isolate-inl.h" |
10 | 10 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 | 56 |
57 void MergeControlToEnd(JSGraph* jsgraph, Node* node) { | 57 void MergeControlToEnd(JSGraph* jsgraph, Node* node) { |
58 Graph* g = jsgraph->graph(); | 58 Graph* g = jsgraph->graph(); |
59 if (g->end()) { | 59 if (g->end()) { |
60 NodeProperties::MergeControlToEnd(g, jsgraph->common(), node); | 60 NodeProperties::MergeControlToEnd(g, jsgraph->common(), node); |
61 } else { | 61 } else { |
62 g->SetEnd(g->NewNode(jsgraph->common()->End(1), node)); | 62 g->SetEnd(g->NewNode(jsgraph->common()->End(1), node)); |
63 } | 63 } |
64 } | 64 } |
65 | 65 |
| 66 Node* BuildCallToRuntime(Runtime::FunctionId f, JSGraph* jsgraph, |
| 67 Handle<Context> context, Node** parameters, |
| 68 int parameter_count, Node** effect_ptr, |
| 69 Node** control_ptr) { |
| 70 // At the moment we only allow 2 parameters. If more parameters are needed, |
| 71 // then the size of {inputs} below has to be increased accordingly. |
| 72 DCHECK(parameter_count <= 2); |
| 73 const Runtime::Function* fun = Runtime::FunctionForId(f); |
| 74 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( |
| 75 jsgraph->zone(), f, fun->nargs, Operator::kNoProperties, |
| 76 CallDescriptor::kNoFlags); |
| 77 // CEntryStubConstant nodes have to be created and cached in the main |
| 78 // thread. At the moment this is only done for CEntryStubConstant(1). |
| 79 DCHECK_EQ(1, fun->result_size); |
| 80 Node* inputs[8]; |
| 81 int count = 0; |
| 82 inputs[count++] = jsgraph->CEntryStubConstant(fun->result_size); |
| 83 for (int i = 0; i < parameter_count; i++) { |
| 84 inputs[count++] = parameters[i]; |
| 85 } |
| 86 inputs[count++] = jsgraph->ExternalConstant( |
| 87 ExternalReference(f, jsgraph->isolate())); // ref |
| 88 inputs[count++] = jsgraph->Int32Constant(fun->nargs); // arity |
| 89 inputs[count++] = jsgraph->HeapConstant(context); // context |
| 90 inputs[count++] = *effect_ptr; |
| 91 inputs[count++] = *control_ptr; |
| 92 |
| 93 Node* node = |
| 94 jsgraph->graph()->NewNode(jsgraph->common()->Call(desc), count, inputs); |
| 95 *effect_ptr = node; |
| 96 return node; |
| 97 } |
| 98 |
66 } // namespace | 99 } // namespace |
67 | 100 |
68 // A helper that handles building graph fragments for trapping. | 101 // A helper that handles building graph fragments for trapping. |
69 // To avoid generating a ton of redundant code that just calls the runtime | 102 // To avoid generating a ton of redundant code that just calls the runtime |
70 // to trap, we generate a per-trap-reason block of code that all trap sites | 103 // to trap, we generate a per-trap-reason block of code that all trap sites |
71 // in this function will branch to. | 104 // in this function will branch to. |
72 class WasmTrapHelper : public ZoneObject { | 105 class WasmTrapHelper : public ZoneObject { |
73 public: | 106 public: |
74 explicit WasmTrapHelper(WasmGraphBuilder* builder) | 107 explicit WasmTrapHelper(WasmGraphBuilder* builder) |
75 : builder_(builder), | 108 : builder_(builder), |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 1), | 252 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 1), |
220 reason_node, *control_ptr); | 253 reason_node, *control_ptr); |
221 trap_position_ = | 254 trap_position_ = |
222 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 1), | 255 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 1), |
223 position_node, *control_ptr); | 256 position_node, *control_ptr); |
224 | 257 |
225 Node* trap_reason_smi = builder_->BuildChangeInt32ToSmi(trap_reason_); | 258 Node* trap_reason_smi = builder_->BuildChangeInt32ToSmi(trap_reason_); |
226 Node* trap_position_smi = builder_->BuildChangeInt32ToSmi(trap_position_); | 259 Node* trap_position_smi = builder_->BuildChangeInt32ToSmi(trap_position_); |
227 | 260 |
228 if (module && !module->instance->context.is_null()) { | 261 if (module && !module->instance->context.is_null()) { |
229 // Use the module context to call the runtime to throw an exception. | 262 Node* parameters[] = {trap_reason_smi, // message id |
230 Runtime::FunctionId f = Runtime::kThrowWasmError; | 263 trap_position_smi}; // byte position |
231 const Runtime::Function* fun = Runtime::FunctionForId(f); | 264 BuildCallToRuntime(Runtime::kThrowWasmError, jsgraph(), |
232 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( | 265 module->instance->context, parameters, |
233 jsgraph()->zone(), f, fun->nargs, Operator::kNoProperties, | 266 arraysize(parameters), effect_ptr, control_ptr); |
234 CallDescriptor::kNoFlags); | |
235 // CEntryStubConstant nodes have to be created and cached in the main | |
236 // thread. At the moment this is only done for CEntryStubConstant(1). | |
237 DCHECK_EQ(1, fun->result_size); | |
238 Node* inputs[] = { | |
239 jsgraph()->CEntryStubConstant(fun->result_size), // C entry | |
240 trap_reason_smi, // message id | |
241 trap_position_smi, // byte position | |
242 jsgraph()->ExternalConstant( | |
243 ExternalReference(f, jsgraph()->isolate())), // ref | |
244 jsgraph()->Int32Constant(fun->nargs), // arity | |
245 builder_->HeapConstant(module->instance->context), // context | |
246 *effect_ptr, | |
247 *control_ptr}; | |
248 | |
249 Node* node = graph()->NewNode( | |
250 common()->Call(desc), static_cast<int>(arraysize(inputs)), inputs); | |
251 *effect_ptr = node; | |
252 *control_ptr = graph()->NewNode(common()->IfSuccess(), node); | |
253 } | 267 } |
254 if (false) { | 268 if (false) { |
255 // End the control flow with a throw | 269 // End the control flow with a throw |
256 Node* thrw = | 270 Node* thrw = |
257 graph()->NewNode(common()->Throw(), jsgraph()->ZeroConstant(), | 271 graph()->NewNode(common()->Throw(), jsgraph()->ZeroConstant(), |
258 *effect_ptr, *control_ptr); | 272 *effect_ptr, *control_ptr); |
259 end = thrw; | 273 end = thrw; |
260 } else { | 274 } else { |
261 // End the control flow with returning 0xdeadbeef | 275 // End the control flow with returning 0xdeadbeef |
262 Node* ret_value = GetTrapValue(builder_->GetFunctionSignature()); | 276 Node* ret_value = GetTrapValue(builder_->GetFunctionSignature()); |
(...skipping 1917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2180 value = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), vsmi, | 2194 value = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), vsmi, |
2181 vbox, control); | 2195 vbox, control); |
2182 return value; | 2196 return value; |
2183 } | 2197 } |
2184 | 2198 |
2185 Node* WasmGraphBuilder::ToJS(Node* node, wasm::LocalType type) { | 2199 Node* WasmGraphBuilder::ToJS(Node* node, wasm::LocalType type) { |
2186 switch (type) { | 2200 switch (type) { |
2187 case wasm::kAstI32: | 2201 case wasm::kAstI32: |
2188 return BuildChangeInt32ToTagged(node); | 2202 return BuildChangeInt32ToTagged(node); |
2189 case wasm::kAstI64: | 2203 case wasm::kAstI64: |
2190 // TODO(titzer): i64->JS has no good solution right now. Using lower 32 | 2204 DCHECK(module_ && !module_->instance->context.is_null()); |
2191 // bits. | 2205 // Throw a TypeError. |
2192 if (jsgraph()->machine()->Is64()) { | 2206 return BuildCallToRuntime(Runtime::kWasmThrowTypeError, jsgraph(), |
2193 // On 32 bit platforms we do not have to do the truncation because the | 2207 module_->instance->context, nullptr, 0, effect_, |
2194 // node we get in as a parameter only contains the low word anyways. | 2208 control_); |
2195 node = graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), | |
2196 node); | |
2197 } | |
2198 return BuildChangeInt32ToTagged(node); | |
2199 case wasm::kAstF32: | 2209 case wasm::kAstF32: |
2200 node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(), | 2210 node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(), |
2201 node); | 2211 node); |
2202 return BuildChangeFloat64ToTagged(node); | 2212 return BuildChangeFloat64ToTagged(node); |
2203 case wasm::kAstF64: | 2213 case wasm::kAstF64: |
2204 return BuildChangeFloat64ToTagged(node); | 2214 return BuildChangeFloat64ToTagged(node); |
2205 case wasm::kAstStmt: | 2215 case wasm::kAstStmt: |
2206 return jsgraph()->UndefinedConstant(); | 2216 return jsgraph()->UndefinedConstant(); |
2207 default: | 2217 default: |
2208 UNREACHABLE(); | 2218 UNREACHABLE(); |
2209 return nullptr; | 2219 return nullptr; |
2210 } | 2220 } |
2211 } | 2221 } |
2212 | 2222 |
2213 Node* WasmGraphBuilder::BuildJavaScriptToNumber(Node* node, Node* context, | 2223 Node* WasmGraphBuilder::BuildJavaScriptToNumber(Node* node, Node* context, |
2214 Node* effect, Node* control) { | 2224 Node* effect, Node* control) { |
2215 Callable callable = CodeFactory::ToNumber(jsgraph()->isolate()); | 2225 Callable callable = CodeFactory::ToNumber(jsgraph()->isolate()); |
2216 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 2226 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
2217 jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0, | 2227 jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0, |
2218 CallDescriptor::kNoFlags, Operator::kNoProperties); | 2228 CallDescriptor::kNoFlags, Operator::kNoProperties); |
2219 Node* stub_code = jsgraph()->HeapConstant(callable.code()); | 2229 Node* stub_code = jsgraph()->HeapConstant(callable.code()); |
2220 | 2230 |
2221 Node* result = graph()->NewNode(jsgraph()->common()->Call(desc), stub_code, | 2231 Node* result = graph()->NewNode(jsgraph()->common()->Call(desc), stub_code, |
2222 node, context, effect, control); | 2232 node, context, effect, control); |
2223 | 2233 |
2224 *effect_ = result; | 2234 *effect_ = result; |
2225 *control_ = graph()->NewNode(jsgraph()->common()->IfSuccess(), result); | |
2226 | 2235 |
2227 return result; | 2236 return result; |
2228 } | 2237 } |
2229 | 2238 |
2230 bool CanCover(Node* value, IrOpcode::Value opcode) { | 2239 bool CanCover(Node* value, IrOpcode::Value opcode) { |
2231 if (value->opcode() != opcode) return false; | 2240 if (value->opcode() != opcode) return false; |
2232 bool first = true; | 2241 bool first = true; |
2233 for (Edge const edge : value->use_edges()) { | 2242 for (Edge const edge : value->use_edges()) { |
2234 if (NodeProperties::IsControlEdge(edge)) continue; | 2243 if (NodeProperties::IsControlEdge(edge)) continue; |
2235 if (NodeProperties::IsEffectEdge(edge)) continue; | 2244 if (NodeProperties::IsEffectEdge(edge)) continue; |
(...skipping 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3227 function_->code_start_offset), | 3236 function_->code_start_offset), |
3228 compile_ms); | 3237 compile_ms); |
3229 } | 3238 } |
3230 | 3239 |
3231 return code; | 3240 return code; |
3232 } | 3241 } |
3233 | 3242 |
3234 } // namespace compiler | 3243 } // namespace compiler |
3235 } // namespace internal | 3244 } // namespace internal |
3236 } // namespace v8 | 3245 } // namespace v8 |
OLD | NEW |