| 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 | 
|---|