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 "src/isolate-inl.h" | 7 #include "src/isolate-inl.h" |
8 | 8 |
9 #include "src/base/platform/elapsed-timer.h" | 9 #include "src/base/platform/elapsed-timer.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
11 | 11 |
12 #include "src/compiler/access-builder.h" | 12 #include "src/compiler/access-builder.h" |
13 #include "src/compiler/change-lowering.h" | |
14 #include "src/compiler/common-operator.h" | 13 #include "src/compiler/common-operator.h" |
15 #include "src/compiler/diamond.h" | 14 #include "src/compiler/diamond.h" |
16 #include "src/compiler/graph.h" | 15 #include "src/compiler/graph.h" |
17 #include "src/compiler/graph-visualizer.h" | 16 #include "src/compiler/graph-visualizer.h" |
18 #include "src/compiler/instruction-selector.h" | 17 #include "src/compiler/instruction-selector.h" |
19 #include "src/compiler/int64-lowering.h" | 18 #include "src/compiler/int64-lowering.h" |
20 #include "src/compiler/js-generic-lowering.h" | 19 #include "src/compiler/js-generic-lowering.h" |
21 #include "src/compiler/js-graph.h" | 20 #include "src/compiler/js-graph.h" |
22 #include "src/compiler/js-operator.h" | 21 #include "src/compiler/js-operator.h" |
23 #include "src/compiler/linkage.h" | 22 #include "src/compiler/linkage.h" |
24 #include "src/compiler/machine-operator.h" | 23 #include "src/compiler/machine-operator.h" |
25 #include "src/compiler/node-matchers.h" | 24 #include "src/compiler/node-matchers.h" |
26 #include "src/compiler/pipeline.h" | 25 #include "src/compiler/pipeline.h" |
27 #include "src/compiler/simplified-lowering.h" | |
28 #include "src/compiler/simplified-operator.h" | |
29 #include "src/compiler/source-position.h" | 26 #include "src/compiler/source-position.h" |
30 #include "src/compiler/typer.h" | |
31 | 27 |
32 #include "src/code-factory.h" | 28 #include "src/code-factory.h" |
33 #include "src/code-stubs.h" | 29 #include "src/code-stubs.h" |
34 #include "src/factory.h" | 30 #include "src/factory.h" |
35 #include "src/log-inl.h" | 31 #include "src/log-inl.h" |
36 #include "src/profiler/cpu-profiler.h" | 32 #include "src/profiler/cpu-profiler.h" |
37 | 33 |
38 #include "src/wasm/ast-decoder.h" | 34 #include "src/wasm/ast-decoder.h" |
39 #include "src/wasm/wasm-module.h" | 35 #include "src/wasm/wasm-module.h" |
40 #include "src/wasm/wasm-opcodes.h" | 36 #include "src/wasm/wasm-opcodes.h" |
(...skipping 2026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2067 graph()->NewNode(machine->Word32Shl(), key, | 2063 graph()->NewNode(machine->Word32Shl(), key, |
2068 Int32Constant(kPointerSizeLog2)), | 2064 Int32Constant(kPointerSizeLog2)), |
2069 Int32Constant(offset)), | 2065 Int32Constant(offset)), |
2070 *effect_, *control_); | 2066 *effect_, *control_); |
2071 | 2067 |
2072 args[0] = load_code; | 2068 args[0] = load_code; |
2073 wasm::FunctionSig* sig = module_->GetSignature(index); | 2069 wasm::FunctionSig* sig = module_->GetSignature(index); |
2074 return BuildWasmCall(sig, args); | 2070 return BuildWasmCall(sig, args); |
2075 } | 2071 } |
2076 | 2072 |
| 2073 Node* WasmGraphBuilder::BuildI32Rol(Node* left, Node* right) { |
| 2074 // Implement Rol by Ror since TurboFan does not have Rol opcode. |
| 2075 // TODO(weiliang): support Word32Rol opcode in TurboFan. |
| 2076 Int32Matcher m(right); |
| 2077 if (m.HasValue()) { |
| 2078 return Binop(wasm::kExprI32Ror, left, |
| 2079 jsgraph()->Int32Constant(32 - m.Value())); |
| 2080 } else { |
| 2081 return Binop(wasm::kExprI32Ror, left, |
| 2082 Binop(wasm::kExprI32Sub, jsgraph()->Int32Constant(32), right)); |
| 2083 } |
| 2084 } |
| 2085 |
| 2086 Node* WasmGraphBuilder::BuildI64Rol(Node* left, Node* right) { |
| 2087 // Implement Rol by Ror since TurboFan does not have Rol opcode. |
| 2088 // TODO(weiliang): support Word64Rol opcode in TurboFan. |
| 2089 Int64Matcher m(right); |
| 2090 if (m.HasValue()) { |
| 2091 return Binop(wasm::kExprI64Ror, left, |
| 2092 jsgraph()->Int64Constant(64 - m.Value())); |
| 2093 } else { |
| 2094 return Binop(wasm::kExprI64Ror, left, |
| 2095 Binop(wasm::kExprI64Sub, jsgraph()->Int64Constant(64), right)); |
| 2096 } |
| 2097 } |
| 2098 |
| 2099 Node* WasmGraphBuilder::Invert(Node* node) { |
| 2100 return Unop(wasm::kExprI32Eqz, node); |
| 2101 } |
| 2102 |
| 2103 Node* WasmGraphBuilder::BuildChangeInt32ToTagged(Node* value) { |
| 2104 MachineOperatorBuilder* machine = jsgraph()->machine(); |
| 2105 CommonOperatorBuilder* common = jsgraph()->common(); |
| 2106 |
| 2107 if (machine->Is64()) { |
| 2108 return BuildChangeInt32ToSmi(value); |
| 2109 } |
| 2110 |
| 2111 Node* add = graph()->NewNode(machine->Int32AddWithOverflow(), value, value); |
| 2112 |
| 2113 Node* ovf = graph()->NewNode(common->Projection(1), add); |
| 2114 Node* branch = graph()->NewNode(common->Branch(BranchHint::kFalse), ovf, |
| 2115 graph()->start()); |
| 2116 |
| 2117 Node* if_true = graph()->NewNode(common->IfTrue(), branch); |
| 2118 Node* vtrue = BuildAllocateHeapNumberWithValue( |
| 2119 graph()->NewNode(machine->ChangeInt32ToFloat64(), value), if_true); |
| 2120 |
| 2121 Node* if_false = graph()->NewNode(common->IfFalse(), branch); |
| 2122 Node* vfalse = graph()->NewNode(common->Projection(0), add); |
| 2123 |
| 2124 Node* merge = graph()->NewNode(common->Merge(2), if_true, if_false); |
| 2125 Node* phi = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), |
| 2126 vtrue, vfalse, merge); |
| 2127 return phi; |
| 2128 } |
| 2129 |
| 2130 Node* WasmGraphBuilder::BuildChangeFloat64ToTagged(Node* value) { |
| 2131 MachineOperatorBuilder* machine = jsgraph()->machine(); |
| 2132 CommonOperatorBuilder* common = jsgraph()->common(); |
| 2133 |
| 2134 Node* const value32 = graph()->NewNode( |
| 2135 machine->TruncateFloat64ToInt32(TruncationMode::kRoundToZero), value); |
| 2136 Node* check_same = graph()->NewNode( |
| 2137 machine->Float64Equal(), value, |
| 2138 graph()->NewNode(machine->ChangeInt32ToFloat64(), value32)); |
| 2139 Node* branch_same = |
| 2140 graph()->NewNode(common->Branch(), check_same, graph()->start()); |
| 2141 |
| 2142 Node* if_smi = graph()->NewNode(common->IfTrue(), branch_same); |
| 2143 Node* vsmi; |
| 2144 Node* if_box = graph()->NewNode(common->IfFalse(), branch_same); |
| 2145 Node* vbox; |
| 2146 |
| 2147 // We only need to check for -0 if the {value} can potentially contain -0. |
| 2148 Node* check_zero = graph()->NewNode(machine->Word32Equal(), value32, |
| 2149 jsgraph()->Int32Constant(0)); |
| 2150 Node* branch_zero = |
| 2151 graph()->NewNode(common->Branch(BranchHint::kFalse), check_zero, if_smi); |
| 2152 |
| 2153 Node* if_zero = graph()->NewNode(common->IfTrue(), branch_zero); |
| 2154 Node* if_notzero = graph()->NewNode(common->IfFalse(), branch_zero); |
| 2155 |
| 2156 // In case of 0, we need to check the high bits for the IEEE -0 pattern. |
| 2157 Node* check_negative = graph()->NewNode( |
| 2158 machine->Int32LessThan(), |
| 2159 graph()->NewNode(machine->Float64ExtractHighWord32(), value), |
| 2160 jsgraph()->Int32Constant(0)); |
| 2161 Node* branch_negative = graph()->NewNode(common->Branch(BranchHint::kFalse), |
| 2162 check_negative, if_zero); |
| 2163 |
| 2164 Node* if_negative = graph()->NewNode(common->IfTrue(), branch_negative); |
| 2165 Node* if_notnegative = graph()->NewNode(common->IfFalse(), branch_negative); |
| 2166 |
| 2167 // We need to create a box for negative 0. |
| 2168 if_smi = graph()->NewNode(common->Merge(2), if_notzero, if_notnegative); |
| 2169 if_box = graph()->NewNode(common->Merge(2), if_box, if_negative); |
| 2170 |
| 2171 // On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit |
| 2172 // machines we need to deal with potential overflow and fallback to boxing. |
| 2173 if (machine->Is64()) { |
| 2174 vsmi = BuildChangeInt32ToSmi(value32); |
| 2175 } else { |
| 2176 Node* smi_tag = |
| 2177 graph()->NewNode(machine->Int32AddWithOverflow(), value32, value32); |
| 2178 |
| 2179 Node* check_ovf = graph()->NewNode(common->Projection(1), smi_tag); |
| 2180 Node* branch_ovf = |
| 2181 graph()->NewNode(common->Branch(BranchHint::kFalse), check_ovf, if_smi); |
| 2182 |
| 2183 Node* if_ovf = graph()->NewNode(common->IfTrue(), branch_ovf); |
| 2184 if_box = graph()->NewNode(common->Merge(2), if_ovf, if_box); |
| 2185 |
| 2186 if_smi = graph()->NewNode(common->IfFalse(), branch_ovf); |
| 2187 vsmi = graph()->NewNode(common->Projection(0), smi_tag); |
| 2188 } |
| 2189 |
| 2190 // Allocate the box for the {value}. |
| 2191 vbox = BuildAllocateHeapNumberWithValue(value, if_box); |
| 2192 |
| 2193 Node* control = graph()->NewNode(common->Merge(2), if_smi, if_box); |
| 2194 value = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), vsmi, |
| 2195 vbox, control); |
| 2196 return value; |
| 2197 } |
2077 | 2198 |
2078 Node* WasmGraphBuilder::ToJS(Node* node, Node* context, wasm::LocalType type) { | 2199 Node* WasmGraphBuilder::ToJS(Node* node, Node* context, wasm::LocalType type) { |
2079 SimplifiedOperatorBuilder simplified(jsgraph()->zone()); | |
2080 switch (type) { | 2200 switch (type) { |
2081 case wasm::kAstI32: | 2201 case wasm::kAstI32: |
2082 return graph()->NewNode(simplified.ChangeInt32ToTagged(), node); | 2202 return BuildChangeInt32ToTagged(node); |
2083 case wasm::kAstI64: | 2203 case wasm::kAstI64: |
2084 // TODO(titzer): i64->JS has no good solution right now. Using lower 32 | 2204 // TODO(titzer): i64->JS has no good solution right now. Using lower 32 |
2085 // bits. | 2205 // bits. |
2086 node = | 2206 node = |
2087 graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), node); | 2207 graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), node); |
2088 return graph()->NewNode(simplified.ChangeInt32ToTagged(), node); | 2208 return BuildChangeInt32ToTagged(node); |
2089 case wasm::kAstF32: | 2209 case wasm::kAstF32: |
2090 node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(), | 2210 node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(), |
2091 node); | 2211 node); |
2092 return graph()->NewNode(simplified.ChangeFloat64ToTagged(), node); | 2212 return BuildChangeFloat64ToTagged(node); |
2093 case wasm::kAstF64: | 2213 case wasm::kAstF64: |
2094 return graph()->NewNode(simplified.ChangeFloat64ToTagged(), node); | 2214 return BuildChangeFloat64ToTagged(node); |
2095 case wasm::kAstStmt: | 2215 case wasm::kAstStmt: |
2096 return jsgraph()->UndefinedConstant(); | 2216 return jsgraph()->UndefinedConstant(); |
2097 default: | 2217 default: |
2098 UNREACHABLE(); | 2218 UNREACHABLE(); |
2099 return nullptr; | 2219 return nullptr; |
2100 } | 2220 } |
2101 } | 2221 } |
2102 | 2222 |
2103 Node* WasmGraphBuilder::BuildJavaScriptToNumber(Node* node, Node* context, | 2223 Node* WasmGraphBuilder::BuildJavaScriptToNumber(Node* node, Node* context, |
2104 Node* effect, Node* control) { | 2224 Node* effect, Node* control) { |
2105 Callable callable = CodeFactory::ToNumber(jsgraph()->isolate()); | 2225 Callable callable = CodeFactory::ToNumber(jsgraph()->isolate()); |
2106 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 2226 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
2107 jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0, | 2227 jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0, |
2108 CallDescriptor::kNoFlags, Operator::kNoProperties); | 2228 CallDescriptor::kNoFlags, Operator::kNoProperties); |
2109 Node* stub_code = jsgraph()->HeapConstant(callable.code()); | 2229 Node* stub_code = jsgraph()->HeapConstant(callable.code()); |
2110 | 2230 |
2111 Node* result = graph()->NewNode(jsgraph()->common()->Call(desc), stub_code, | 2231 Node* result = graph()->NewNode(jsgraph()->common()->Call(desc), stub_code, |
2112 node, context, effect, control); | 2232 node, context, effect, control); |
2113 | 2233 |
2114 *control_ = result; | 2234 *control_ = result; |
2115 *effect_ = result; | 2235 *effect_ = result; |
2116 | 2236 |
2117 return result; | 2237 return result; |
2118 } | 2238 } |
2119 | 2239 |
| 2240 bool CanCover(Node* value, IrOpcode::Value opcode) { |
| 2241 if (value->opcode() != opcode) return false; |
| 2242 bool first = true; |
| 2243 for (Edge const edge : value->use_edges()) { |
| 2244 if (NodeProperties::IsControlEdge(edge)) continue; |
| 2245 if (NodeProperties::IsEffectEdge(edge)) continue; |
| 2246 DCHECK(NodeProperties::IsValueEdge(edge)); |
| 2247 if (!first) return false; |
| 2248 first = false; |
| 2249 } |
| 2250 return true; |
| 2251 } |
| 2252 |
| 2253 Node* WasmGraphBuilder::BuildChangeTaggedToFloat64(Node* value) { |
| 2254 MachineOperatorBuilder* machine = jsgraph()->machine(); |
| 2255 CommonOperatorBuilder* common = jsgraph()->common(); |
| 2256 |
| 2257 if (CanCover(value, IrOpcode::kJSToNumber)) { |
| 2258 // ChangeTaggedToFloat64(JSToNumber(x)) => |
| 2259 // if IsSmi(x) then ChangeSmiToFloat64(x) |
| 2260 // else let y = JSToNumber(x) in |
| 2261 // if IsSmi(y) then ChangeSmiToFloat64(y) |
| 2262 // else BuildLoadHeapNumberValue(y) |
| 2263 Node* object = NodeProperties::GetValueInput(value, 0); |
| 2264 Node* context = NodeProperties::GetContextInput(value); |
| 2265 Node* frame_state = NodeProperties::GetFrameStateInput(value, 0); |
| 2266 Node* effect = NodeProperties::GetEffectInput(value); |
| 2267 Node* control = NodeProperties::GetControlInput(value); |
| 2268 |
| 2269 const Operator* merge_op = common->Merge(2); |
| 2270 const Operator* ephi_op = common->EffectPhi(2); |
| 2271 const Operator* phi_op = common->Phi(MachineRepresentation::kFloat64, 2); |
| 2272 |
| 2273 Node* check1 = BuildTestNotSmi(object); |
| 2274 Node* branch1 = |
| 2275 graph()->NewNode(common->Branch(BranchHint::kFalse), check1, control); |
| 2276 |
| 2277 Node* if_true1 = graph()->NewNode(common->IfTrue(), branch1); |
| 2278 Node* vtrue1 = graph()->NewNode(value->op(), object, context, frame_state, |
| 2279 effect, if_true1); |
| 2280 Node* etrue1 = vtrue1; |
| 2281 |
| 2282 Node* check2 = BuildTestNotSmi(vtrue1); |
| 2283 Node* branch2 = graph()->NewNode(common->Branch(), check2, if_true1); |
| 2284 |
| 2285 Node* if_true2 = graph()->NewNode(common->IfTrue(), branch2); |
| 2286 Node* vtrue2 = BuildLoadHeapNumberValue(vtrue1, if_true2); |
| 2287 |
| 2288 Node* if_false2 = graph()->NewNode(common->IfFalse(), branch2); |
| 2289 Node* vfalse2 = BuildChangeSmiToFloat64(vtrue1); |
| 2290 |
| 2291 if_true1 = graph()->NewNode(merge_op, if_true2, if_false2); |
| 2292 vtrue1 = graph()->NewNode(phi_op, vtrue2, vfalse2, if_true1); |
| 2293 |
| 2294 Node* if_false1 = graph()->NewNode(common->IfFalse(), branch1); |
| 2295 Node* vfalse1 = BuildChangeSmiToFloat64(object); |
| 2296 Node* efalse1 = effect; |
| 2297 |
| 2298 Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1); |
| 2299 Node* ephi1 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1); |
| 2300 Node* phi1 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1); |
| 2301 |
| 2302 // Wire the new diamond into the graph, {JSToNumber} can still throw. |
| 2303 NodeProperties::ReplaceUses(value, phi1, ephi1, etrue1, etrue1); |
| 2304 |
| 2305 // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from |
| 2306 // the node and places it inside the diamond. Come up with a helper method! |
| 2307 for (Node* use : etrue1->uses()) { |
| 2308 if (use->opcode() == IrOpcode::kIfSuccess) { |
| 2309 use->ReplaceUses(merge1); |
| 2310 NodeProperties::ReplaceControlInput(branch2, use); |
| 2311 } |
| 2312 } |
| 2313 return phi1; |
| 2314 } |
| 2315 |
| 2316 Node* check = BuildTestNotSmi(value); |
| 2317 Node* branch = graph()->NewNode(common->Branch(BranchHint::kFalse), check, |
| 2318 graph()->start()); |
| 2319 |
| 2320 Node* if_not_smi = graph()->NewNode(common->IfTrue(), branch); |
| 2321 |
| 2322 Node* vnot_smi; |
| 2323 Node* check_undefined = graph()->NewNode(machine->WordEqual(), value, |
| 2324 jsgraph()->UndefinedConstant()); |
| 2325 Node* branch_undefined = graph()->NewNode(common->Branch(BranchHint::kFalse), |
| 2326 check_undefined, if_not_smi); |
| 2327 |
| 2328 Node* if_undefined = graph()->NewNode(common->IfTrue(), branch_undefined); |
| 2329 Node* vundefined = |
| 2330 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN()); |
| 2331 |
| 2332 Node* if_not_undefined = |
| 2333 graph()->NewNode(common->IfFalse(), branch_undefined); |
| 2334 Node* vheap_number = BuildLoadHeapNumberValue(value, if_not_undefined); |
| 2335 |
| 2336 if_not_smi = |
| 2337 graph()->NewNode(common->Merge(2), if_undefined, if_not_undefined); |
| 2338 vnot_smi = graph()->NewNode(common->Phi(MachineRepresentation::kFloat64, 2), |
| 2339 vundefined, vheap_number, if_not_smi); |
| 2340 |
| 2341 Node* if_smi = graph()->NewNode(common->IfFalse(), branch); |
| 2342 Node* vfrom_smi = BuildChangeSmiToFloat64(value); |
| 2343 |
| 2344 Node* merge = graph()->NewNode(common->Merge(2), if_not_smi, if_smi); |
| 2345 Node* phi = graph()->NewNode(common->Phi(MachineRepresentation::kFloat64, 2), |
| 2346 vnot_smi, vfrom_smi, merge); |
| 2347 |
| 2348 return phi; |
| 2349 } |
| 2350 |
2120 Node* WasmGraphBuilder::FromJS(Node* node, Node* context, | 2351 Node* WasmGraphBuilder::FromJS(Node* node, Node* context, |
2121 wasm::LocalType type) { | 2352 wasm::LocalType type) { |
2122 // Do a JavaScript ToNumber. | 2353 // Do a JavaScript ToNumber. |
2123 Node* num = BuildJavaScriptToNumber(node, context, *effect_, *control_); | 2354 Node* num = BuildJavaScriptToNumber(node, context, *effect_, *control_); |
2124 | 2355 |
2125 // Change representation. | 2356 // Change representation. |
2126 SimplifiedOperatorBuilder simplified(jsgraph()->zone()); | 2357 SimplifiedOperatorBuilder simplified(jsgraph()->zone()); |
2127 num = graph()->NewNode(simplified.ChangeTaggedToFloat64(), num); | 2358 num = BuildChangeTaggedToFloat64(num); |
2128 | 2359 |
2129 switch (type) { | 2360 switch (type) { |
2130 case wasm::kAstI32: { | 2361 case wasm::kAstI32: { |
2131 num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToInt32( | 2362 num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToInt32( |
2132 TruncationMode::kJavaScript), | 2363 TruncationMode::kJavaScript), |
2133 num); | 2364 num); |
2134 break; | 2365 break; |
2135 } | 2366 } |
2136 case wasm::kAstI64: | 2367 case wasm::kAstI64: |
2137 // TODO(titzer): JS->i64 has no good solution right now. Using 32 bits. | 2368 // TODO(titzer): JS->i64 has no good solution right now. Using 32 bits. |
(...skipping 11 matching lines...) Expand all Loading... |
2149 case wasm::kAstStmt: | 2380 case wasm::kAstStmt: |
2150 num = jsgraph()->Int32Constant(0); | 2381 num = jsgraph()->Int32Constant(0); |
2151 break; | 2382 break; |
2152 default: | 2383 default: |
2153 UNREACHABLE(); | 2384 UNREACHABLE(); |
2154 return nullptr; | 2385 return nullptr; |
2155 } | 2386 } |
2156 return num; | 2387 return num; |
2157 } | 2388 } |
2158 | 2389 |
2159 Node* WasmGraphBuilder::BuildI32Rol(Node* left, Node* right) { | 2390 Node* WasmGraphBuilder::BuildChangeInt32ToSmi(Node* value) { |
2160 // Implement Rol by Ror since TurboFan does not have Rol opcode. | 2391 if (jsgraph()->machine()->Is64()) { |
2161 // TODO(weiliang): support Word32Rol opcode in TurboFan. | 2392 value = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), value); |
2162 Int32Matcher m(right); | |
2163 if (m.HasValue()) { | |
2164 return Binop(wasm::kExprI32Ror, left, | |
2165 jsgraph()->Int32Constant(32 - m.Value())); | |
2166 } else { | |
2167 return Binop(wasm::kExprI32Ror, left, | |
2168 Binop(wasm::kExprI32Sub, jsgraph()->Int32Constant(32), right)); | |
2169 } | 2393 } |
| 2394 return graph()->NewNode(jsgraph()->machine()->WordShl(), value, |
| 2395 BuildSmiShiftBitsConstant()); |
2170 } | 2396 } |
2171 | 2397 |
2172 Node* WasmGraphBuilder::BuildI64Rol(Node* left, Node* right) { | 2398 Node* WasmGraphBuilder::BuildChangeSmiToInt32(Node* value) { |
2173 // Implement Rol by Ror since TurboFan does not have Rol opcode. | 2399 value = graph()->NewNode(jsgraph()->machine()->WordSar(), value, |
2174 // TODO(weiliang): support Word64Rol opcode in TurboFan. | 2400 BuildSmiShiftBitsConstant()); |
2175 Int64Matcher m(right); | 2401 if (jsgraph()->machine()->Is64()) { |
2176 if (m.HasValue()) { | 2402 value = |
2177 return Binop(wasm::kExprI64Ror, left, | 2403 graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), value); |
2178 jsgraph()->Int64Constant(64 - m.Value())); | |
2179 } else { | |
2180 return Binop(wasm::kExprI64Ror, left, | |
2181 Binop(wasm::kExprI64Sub, jsgraph()->Int64Constant(64), right)); | |
2182 } | 2404 } |
| 2405 return value; |
2183 } | 2406 } |
2184 | 2407 |
2185 Node* WasmGraphBuilder::Invert(Node* node) { | 2408 Node* WasmGraphBuilder::BuildChangeSmiToFloat64(Node* value) { |
2186 return Unop(wasm::kExprI32Eqz, node); | 2409 return graph()->NewNode(jsgraph()->machine()->ChangeInt32ToFloat64(), |
| 2410 BuildChangeSmiToInt32(value)); |
2187 } | 2411 } |
2188 | 2412 |
| 2413 Node* WasmGraphBuilder::BuildTestNotSmi(Node* value) { |
| 2414 STATIC_ASSERT(kSmiTag == 0); |
| 2415 STATIC_ASSERT(kSmiTagMask == 1); |
| 2416 return graph()->NewNode(jsgraph()->machine()->WordAnd(), value, |
| 2417 jsgraph()->IntPtrConstant(kSmiTagMask)); |
| 2418 } |
| 2419 |
| 2420 Node* WasmGraphBuilder::BuildSmiShiftBitsConstant() { |
| 2421 return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize); |
| 2422 } |
| 2423 |
| 2424 Node* WasmGraphBuilder::BuildAllocateHeapNumberWithValue(Node* value, |
| 2425 Node* control) { |
| 2426 MachineOperatorBuilder* machine = jsgraph()->machine(); |
| 2427 CommonOperatorBuilder* common = jsgraph()->common(); |
| 2428 // The AllocateHeapNumberStub does not use the context, so we can safely pass |
| 2429 // in Smi zero here. |
| 2430 Callable callable = CodeFactory::AllocateHeapNumber(jsgraph()->isolate()); |
| 2431 Node* target = jsgraph()->HeapConstant(callable.code()); |
| 2432 Node* context = jsgraph()->NoContextConstant(); |
| 2433 Node* effect = graph()->NewNode(common->BeginRegion(), graph()->start()); |
| 2434 if (!allocate_heap_number_operator_.is_set()) { |
| 2435 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor( |
| 2436 jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0, |
| 2437 CallDescriptor::kNoFlags, Operator::kNoThrow); |
| 2438 allocate_heap_number_operator_.set(common->Call(descriptor)); |
| 2439 } |
| 2440 Node* heap_number = graph()->NewNode(allocate_heap_number_operator_.get(), |
| 2441 target, context, effect, control); |
| 2442 Node* store = |
| 2443 graph()->NewNode(machine->Store(StoreRepresentation( |
| 2444 MachineRepresentation::kFloat64, kNoWriteBarrier)), |
| 2445 heap_number, BuildHeapNumberValueIndexConstant(), value, |
| 2446 heap_number, control); |
| 2447 return graph()->NewNode(common->FinishRegion(), heap_number, store); |
| 2448 } |
| 2449 |
| 2450 Node* WasmGraphBuilder::BuildLoadHeapNumberValue(Node* value, Node* control) { |
| 2451 return graph()->NewNode(jsgraph()->machine()->Load(MachineType::Float64()), |
| 2452 value, BuildHeapNumberValueIndexConstant(), |
| 2453 graph()->start(), control); |
| 2454 } |
| 2455 |
| 2456 Node* WasmGraphBuilder::BuildHeapNumberValueIndexConstant() { |
| 2457 return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag); |
| 2458 } |
2189 | 2459 |
2190 void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code, | 2460 void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code, |
2191 wasm::FunctionSig* sig) { | 2461 wasm::FunctionSig* sig) { |
2192 int params = static_cast<int>(sig->parameter_count()); | 2462 int params = static_cast<int>(sig->parameter_count()); |
2193 int count = params + 3; | 2463 int count = params + 3; |
2194 Node** args = Buffer(count); | 2464 Node** args = Buffer(count); |
2195 | 2465 |
2196 // Build the start and the JS parameter nodes. | 2466 // Build the start and the JS parameter nodes. |
2197 Node* start = Start(params + 5); | 2467 Node* start = Start(params + 5); |
2198 *control_ = start; | 2468 *control_ = start; |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2529 WasmGraphBuilder builder(&zone, &jsgraph, func->sig); | 2799 WasmGraphBuilder builder(&zone, &jsgraph, func->sig); |
2530 builder.set_control_ptr(&control); | 2800 builder.set_control_ptr(&control); |
2531 builder.set_effect_ptr(&effect); | 2801 builder.set_effect_ptr(&effect); |
2532 builder.set_module(module); | 2802 builder.set_module(module); |
2533 builder.BuildJSToWasmWrapper(wasm_code, func->sig); | 2803 builder.BuildJSToWasmWrapper(wasm_code, func->sig); |
2534 | 2804 |
2535 //---------------------------------------------------------------------------- | 2805 //---------------------------------------------------------------------------- |
2536 // Run the compilation pipeline. | 2806 // Run the compilation pipeline. |
2537 //---------------------------------------------------------------------------- | 2807 //---------------------------------------------------------------------------- |
2538 { | 2808 { |
2539 // Changes lowering requires types. | |
2540 Typer typer(isolate, &graph); | |
2541 NodeVector roots(&zone); | |
2542 jsgraph.GetCachedNodes(&roots); | |
2543 typer.Run(roots); | |
2544 | |
2545 // Run generic and change lowering. | |
2546 ChangeLowering changes(&jsgraph); | |
2547 GraphReducer graph_reducer(&zone, &graph, jsgraph.Dead()); | |
2548 graph_reducer.AddReducer(&changes); | |
2549 graph_reducer.ReduceGraph(); | |
2550 | |
2551 if (FLAG_trace_turbo_graph) { // Simple textual RPO. | 2809 if (FLAG_trace_turbo_graph) { // Simple textual RPO. |
2552 OFStream os(stdout); | 2810 OFStream os(stdout); |
2553 os << "-- Graph after change lowering -- " << std::endl; | 2811 os << "-- Graph after change lowering -- " << std::endl; |
2554 os << AsRPO(graph); | 2812 os << AsRPO(graph); |
2555 } | 2813 } |
2556 | 2814 |
2557 // Schedule and compile to machine code. | 2815 // Schedule and compile to machine code. |
2558 int params = static_cast<int>( | 2816 int params = static_cast<int>( |
2559 module->GetFunctionSignature(index)->parameter_count()); | 2817 module->GetFunctionSignature(index)->parameter_count()); |
2560 CallDescriptor* incoming = Linkage::GetJSCallDescriptor( | 2818 CallDescriptor* incoming = Linkage::GetJSCallDescriptor( |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2616 Node* effect = nullptr; | 2874 Node* effect = nullptr; |
2617 | 2875 |
2618 WasmGraphBuilder builder(&zone, &jsgraph, sig); | 2876 WasmGraphBuilder builder(&zone, &jsgraph, sig); |
2619 builder.set_control_ptr(&control); | 2877 builder.set_control_ptr(&control); |
2620 builder.set_effect_ptr(&effect); | 2878 builder.set_effect_ptr(&effect); |
2621 builder.set_module(module); | 2879 builder.set_module(module); |
2622 builder.BuildWasmToJSWrapper(function, sig); | 2880 builder.BuildWasmToJSWrapper(function, sig); |
2623 | 2881 |
2624 Handle<Code> code = Handle<Code>::null(); | 2882 Handle<Code> code = Handle<Code>::null(); |
2625 { | 2883 { |
2626 // Changes lowering requires types. | |
2627 Typer typer(isolate, &graph); | |
2628 NodeVector roots(&zone); | |
2629 jsgraph.GetCachedNodes(&roots); | |
2630 typer.Run(roots); | |
2631 | |
2632 // Run generic and change lowering. | |
2633 ChangeLowering changes(&jsgraph); | |
2634 GraphReducer graph_reducer(&zone, &graph, jsgraph.Dead()); | |
2635 graph_reducer.AddReducer(&changes); | |
2636 graph_reducer.ReduceGraph(); | |
2637 | |
2638 if (FLAG_trace_turbo_graph) { // Simple textual RPO. | 2884 if (FLAG_trace_turbo_graph) { // Simple textual RPO. |
2639 OFStream os(stdout); | 2885 OFStream os(stdout); |
2640 os << "-- Graph after change lowering -- " << std::endl; | 2886 os << "-- Graph after change lowering -- " << std::endl; |
2641 os << AsRPO(graph); | 2887 os << AsRPO(graph); |
2642 } | 2888 } |
2643 | 2889 |
2644 // Schedule and compile to machine code. | 2890 // Schedule and compile to machine code. |
2645 CallDescriptor* incoming = | 2891 CallDescriptor* incoming = |
2646 wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig); | 2892 wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig); |
2647 Code::Flags flags = Code::ComputeFlags(Code::WASM_TO_JS_FUNCTION); | 2893 Code::Flags flags = Code::ComputeFlags(Code::WASM_TO_JS_FUNCTION); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2791 // TODO(bradnelson): Improve histogram handling of size_t. | 3037 // TODO(bradnelson): Improve histogram handling of size_t. |
2792 isolate->counters()->wasm_compile_function_peak_memory_bytes()->AddSample( | 3038 isolate->counters()->wasm_compile_function_peak_memory_bytes()->AddSample( |
2793 static_cast<int>(zone.allocation_size())); | 3039 static_cast<int>(zone.allocation_size())); |
2794 return code; | 3040 return code; |
2795 } | 3041 } |
2796 | 3042 |
2797 | 3043 |
2798 } // namespace compiler | 3044 } // namespace compiler |
2799 } // namespace internal | 3045 } // namespace internal |
2800 } // namespace v8 | 3046 } // namespace v8 |
OLD | NEW |