| 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" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 | 65 |
| 66 void MergeControlToEnd(JSGraph* jsgraph, Node* node) { | 66 void MergeControlToEnd(JSGraph* jsgraph, Node* node) { |
| 67 Graph* g = jsgraph->graph(); | 67 Graph* g = jsgraph->graph(); |
| 68 if (g->end()) { | 68 if (g->end()) { |
| 69 NodeProperties::MergeControlToEnd(g, jsgraph->common(), node); | 69 NodeProperties::MergeControlToEnd(g, jsgraph->common(), node); |
| 70 } else { | 70 } else { |
| 71 g->SetEnd(g->NewNode(jsgraph->common()->End(1), node)); | 71 g->SetEnd(g->NewNode(jsgraph->common()->End(1), node)); |
| 72 } | 72 } |
| 73 } | 73 } |
| 74 | 74 |
| 75 | |
| 76 enum TrapReason { | |
| 77 kTrapUnreachable, | |
| 78 kTrapMemOutOfBounds, | |
| 79 kTrapDivByZero, | |
| 80 kTrapDivUnrepresentable, | |
| 81 kTrapRemByZero, | |
| 82 kTrapFloatUnrepresentable, | |
| 83 kTrapFuncInvalid, | |
| 84 kTrapFuncSigMismatch, | |
| 85 kTrapCount | |
| 86 }; | |
| 87 | |
| 88 | |
| 89 static const char* kTrapMessages[] = { | |
| 90 "unreachable", "memory access out of bounds", | |
| 91 "divide by zero", "divide result unrepresentable", | |
| 92 "remainder by zero", "integer result unrepresentable", | |
| 93 "invalid function", "function signature mismatch"}; | |
| 94 } // namespace | 75 } // namespace |
| 95 | 76 |
| 96 | |
| 97 // A helper that handles building graph fragments for trapping. | 77 // A helper that handles building graph fragments for trapping. |
| 98 // To avoid generating a ton of redundant code that just calls the runtime | 78 // To avoid generating a ton of redundant code that just calls the runtime |
| 99 // to trap, we generate a per-trap-reason block of code that all trap sites | 79 // to trap, we generate a per-trap-reason block of code that all trap sites |
| 100 // in this function will branch to. | 80 // in this function will branch to. |
| 101 class WasmTrapHelper : public ZoneObject { | 81 class WasmTrapHelper : public ZoneObject { |
| 102 public: | 82 public: |
| 103 explicit WasmTrapHelper(WasmGraphBuilder* builder) | 83 explicit WasmTrapHelper(WasmGraphBuilder* builder) |
| 104 : builder_(builder), | 84 : builder_(builder), |
| 105 jsgraph_(builder->jsgraph()), | 85 jsgraph_(builder->jsgraph()), |
| 106 graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) { | 86 graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) { |
| 107 for (int i = 0; i < kTrapCount; i++) traps_[i] = nullptr; | 87 for (int i = 0; i < wasm::kTrapCount; i++) traps_[i] = nullptr; |
| 108 } | 88 } |
| 109 | 89 |
| 110 // Make the current control path trap to unreachable. | 90 // Make the current control path trap to unreachable. |
| 111 void Unreachable() { ConnectTrap(kTrapUnreachable); } | 91 void Unreachable() { ConnectTrap(wasm::kTrapUnreachable); } |
| 112 | 92 |
| 113 // Always trap with the given reason. | 93 // Always trap with the given reason. |
| 114 void TrapAlways(TrapReason reason) { ConnectTrap(reason); } | 94 void TrapAlways(wasm::TrapReason reason) { ConnectTrap(reason); } |
| 115 | 95 |
| 116 // Add a check that traps if {node} is equal to {val}. | 96 // Add a check that traps if {node} is equal to {val}. |
| 117 Node* TrapIfEq32(TrapReason reason, Node* node, int32_t val) { | 97 Node* TrapIfEq32(wasm::TrapReason reason, Node* node, int32_t val) { |
| 118 Int32Matcher m(node); | 98 Int32Matcher m(node); |
| 119 if (m.HasValue() && !m.Is(val)) return graph()->start(); | 99 if (m.HasValue() && !m.Is(val)) return graph()->start(); |
| 120 if (val == 0) { | 100 if (val == 0) { |
| 121 AddTrapIfFalse(reason, node); | 101 AddTrapIfFalse(reason, node); |
| 122 } else { | 102 } else { |
| 123 AddTrapIfTrue(reason, | 103 AddTrapIfTrue(reason, |
| 124 graph()->NewNode(jsgraph()->machine()->Word32Equal(), node, | 104 graph()->NewNode(jsgraph()->machine()->Word32Equal(), node, |
| 125 jsgraph()->Int32Constant(val))); | 105 jsgraph()->Int32Constant(val))); |
| 126 } | 106 } |
| 127 return builder_->Control(); | 107 return builder_->Control(); |
| 128 } | 108 } |
| 129 | 109 |
| 130 // Add a check that traps if {node} is zero. | 110 // Add a check that traps if {node} is zero. |
| 131 Node* ZeroCheck32(TrapReason reason, Node* node) { | 111 Node* ZeroCheck32(wasm::TrapReason reason, Node* node) { |
| 132 return TrapIfEq32(reason, node, 0); | 112 return TrapIfEq32(reason, node, 0); |
| 133 } | 113 } |
| 134 | 114 |
| 135 // Add a check that traps if {node} is equal to {val}. | 115 // Add a check that traps if {node} is equal to {val}. |
| 136 Node* TrapIfEq64(TrapReason reason, Node* node, int64_t val) { | 116 Node* TrapIfEq64(wasm::TrapReason reason, Node* node, int64_t val) { |
| 137 Int64Matcher m(node); | 117 Int64Matcher m(node); |
| 138 if (m.HasValue() && !m.Is(val)) return graph()->start(); | 118 if (m.HasValue() && !m.Is(val)) return graph()->start(); |
| 139 AddTrapIfTrue(reason, | 119 AddTrapIfTrue(reason, |
| 140 graph()->NewNode(jsgraph()->machine()->Word64Equal(), node, | 120 graph()->NewNode(jsgraph()->machine()->Word64Equal(), node, |
| 141 jsgraph()->Int64Constant(val))); | 121 jsgraph()->Int64Constant(val))); |
| 142 return builder_->Control(); | 122 return builder_->Control(); |
| 143 } | 123 } |
| 144 | 124 |
| 145 // Add a check that traps if {node} is zero. | 125 // Add a check that traps if {node} is zero. |
| 146 Node* ZeroCheck64(TrapReason reason, Node* node) { | 126 Node* ZeroCheck64(wasm::TrapReason reason, Node* node) { |
| 147 return TrapIfEq64(reason, node, 0); | 127 return TrapIfEq64(reason, node, 0); |
| 148 } | 128 } |
| 149 | 129 |
| 150 // Add a trap if {cond} is true. | 130 // Add a trap if {cond} is true. |
| 151 void AddTrapIfTrue(TrapReason reason, Node* cond) { | 131 void AddTrapIfTrue(wasm::TrapReason reason, Node* cond) { |
| 152 AddTrapIf(reason, cond, true); | 132 AddTrapIf(reason, cond, true); |
| 153 } | 133 } |
| 154 | 134 |
| 155 // Add a trap if {cond} is false. | 135 // Add a trap if {cond} is false. |
| 156 void AddTrapIfFalse(TrapReason reason, Node* cond) { | 136 void AddTrapIfFalse(wasm::TrapReason reason, Node* cond) { |
| 157 AddTrapIf(reason, cond, false); | 137 AddTrapIf(reason, cond, false); |
| 158 } | 138 } |
| 159 | 139 |
| 160 // Add a trap if {cond} is true or false according to {iftrue}. | 140 // Add a trap if {cond} is true or false according to {iftrue}. |
| 161 void AddTrapIf(TrapReason reason, Node* cond, bool iftrue) { | 141 void AddTrapIf(wasm::TrapReason reason, Node* cond, bool iftrue) { |
| 162 Node** effect_ptr = builder_->effect_; | 142 Node** effect_ptr = builder_->effect_; |
| 163 Node** control_ptr = builder_->control_; | 143 Node** control_ptr = builder_->control_; |
| 164 Node* before = *effect_ptr; | 144 Node* before = *effect_ptr; |
| 165 BranchHint hint = iftrue ? BranchHint::kFalse : BranchHint::kTrue; | 145 BranchHint hint = iftrue ? BranchHint::kFalse : BranchHint::kTrue; |
| 166 Node* branch = graph()->NewNode(common()->Branch(hint), cond, *control_ptr); | 146 Node* branch = graph()->NewNode(common()->Branch(hint), cond, *control_ptr); |
| 167 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 147 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| 168 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 148 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| 169 | 149 |
| 170 *control_ptr = iftrue ? if_true : if_false; | 150 *control_ptr = iftrue ? if_true : if_false; |
| 171 ConnectTrap(reason); | 151 ConnectTrap(reason); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 192 } | 172 } |
| 193 } else { | 173 } else { |
| 194 return jsgraph()->Int32Constant(0xdeadbeef); | 174 return jsgraph()->Int32Constant(0xdeadbeef); |
| 195 } | 175 } |
| 196 } | 176 } |
| 197 | 177 |
| 198 private: | 178 private: |
| 199 WasmGraphBuilder* builder_; | 179 WasmGraphBuilder* builder_; |
| 200 JSGraph* jsgraph_; | 180 JSGraph* jsgraph_; |
| 201 Graph* graph_; | 181 Graph* graph_; |
| 202 Node* traps_[kTrapCount]; | 182 Node* traps_[wasm::kTrapCount]; |
| 203 Node* effects_[kTrapCount]; | 183 Node* effects_[wasm::kTrapCount]; |
| 204 | 184 |
| 205 JSGraph* jsgraph() { return jsgraph_; } | 185 JSGraph* jsgraph() { return jsgraph_; } |
| 206 Graph* graph() { return jsgraph_->graph(); } | 186 Graph* graph() { return jsgraph_->graph(); } |
| 207 CommonOperatorBuilder* common() { return jsgraph()->common(); } | 187 CommonOperatorBuilder* common() { return jsgraph()->common(); } |
| 208 | 188 |
| 209 void ConnectTrap(TrapReason reason) { | 189 void ConnectTrap(wasm::TrapReason reason) { |
| 210 if (traps_[reason] == nullptr) { | 190 if (traps_[reason] == nullptr) { |
| 211 // Create trap code for the first time this trap is used. | 191 // Create trap code for the first time this trap is used. |
| 212 return BuildTrapCode(reason); | 192 return BuildTrapCode(reason); |
| 213 } | 193 } |
| 214 // Connect the current control and effect to the existing trap code. | 194 // Connect the current control and effect to the existing trap code. |
| 215 builder_->AppendToMerge(traps_[reason], builder_->Control()); | 195 builder_->AppendToMerge(traps_[reason], builder_->Control()); |
| 216 builder_->AppendToPhi(traps_[reason], effects_[reason], builder_->Effect()); | 196 builder_->AppendToPhi(traps_[reason], effects_[reason], builder_->Effect()); |
| 217 } | 197 } |
| 218 | 198 |
| 219 void BuildTrapCode(TrapReason reason) { | 199 void BuildTrapCode(wasm::TrapReason reason) { |
| 220 Node* exception = builder_->String(kTrapMessages[reason]); | 200 Node* exception = |
| 201 builder_->String(wasm::WasmOpcodes::TrapReasonName(reason)); |
| 221 Node* end; | 202 Node* end; |
| 222 Node** control_ptr = builder_->control_; | 203 Node** control_ptr = builder_->control_; |
| 223 Node** effect_ptr = builder_->effect_; | 204 Node** effect_ptr = builder_->effect_; |
| 224 wasm::ModuleEnv* module = builder_->module_; | 205 wasm::ModuleEnv* module = builder_->module_; |
| 225 *control_ptr = traps_[reason] = | 206 *control_ptr = traps_[reason] = |
| 226 graph()->NewNode(common()->Merge(1), *control_ptr); | 207 graph()->NewNode(common()->Merge(1), *control_ptr); |
| 227 *effect_ptr = effects_[reason] = | 208 *effect_ptr = effects_[reason] = |
| 228 graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr); | 209 graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr); |
| 229 | 210 |
| 230 if (module && !module->instance->context.is_null()) { | 211 if (module && !module->instance->context.is_null()) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 259 // End the control flow with returning 0xdeadbeef | 240 // End the control flow with returning 0xdeadbeef |
| 260 Node* ret_value = GetTrapValue(builder_->GetFunctionSignature()); | 241 Node* ret_value = GetTrapValue(builder_->GetFunctionSignature()); |
| 261 end = graph()->NewNode(jsgraph()->common()->Return(), ret_value, | 242 end = graph()->NewNode(jsgraph()->common()->Return(), ret_value, |
| 262 *effect_ptr, *control_ptr); | 243 *effect_ptr, *control_ptr); |
| 263 } | 244 } |
| 264 | 245 |
| 265 MergeControlToEnd(jsgraph(), end); | 246 MergeControlToEnd(jsgraph(), end); |
| 266 } | 247 } |
| 267 }; | 248 }; |
| 268 | 249 |
| 269 | |
| 270 WasmGraphBuilder::WasmGraphBuilder(Zone* zone, JSGraph* jsgraph, | 250 WasmGraphBuilder::WasmGraphBuilder(Zone* zone, JSGraph* jsgraph, |
| 271 wasm::FunctionSig* function_signature) | 251 wasm::FunctionSig* function_signature) |
| 272 : zone_(zone), | 252 : zone_(zone), |
| 273 jsgraph_(jsgraph), | 253 jsgraph_(jsgraph), |
| 274 module_(nullptr), | 254 module_(nullptr), |
| 275 mem_buffer_(nullptr), | 255 mem_buffer_(nullptr), |
| 276 mem_size_(nullptr), | 256 mem_size_(nullptr), |
| 277 function_table_(nullptr), | 257 function_table_(nullptr), |
| 278 control_(nullptr), | 258 control_(nullptr), |
| 279 effect_(nullptr), | 259 effect_(nullptr), |
| (...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1164 } | 1144 } |
| 1165 | 1145 |
| 1166 // Truncation of the input value is needed for the overflow check later. | 1146 // Truncation of the input value is needed for the overflow check later. |
| 1167 Node* trunc = Unop(wasm::kExprF32Trunc, input); | 1147 Node* trunc = Unop(wasm::kExprF32Trunc, input); |
| 1168 Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc); | 1148 Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc); |
| 1169 | 1149 |
| 1170 // Convert the result back to f64. If we end up at a different value than the | 1150 // Convert the result back to f64. If we end up at a different value than the |
| 1171 // truncated input value, then there has been an overflow and we trap. | 1151 // truncated input value, then there has been an overflow and we trap. |
| 1172 Node* check = Unop(wasm::kExprF32SConvertI32, result); | 1152 Node* check = Unop(wasm::kExprF32SConvertI32, result); |
| 1173 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); | 1153 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); |
| 1174 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1154 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); |
| 1175 | 1155 |
| 1176 return result; | 1156 return result; |
| 1177 } | 1157 } |
| 1178 | 1158 |
| 1179 | 1159 |
| 1180 Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) { | 1160 Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) { |
| 1181 MachineOperatorBuilder* m = jsgraph()->machine(); | 1161 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1182 if (module_ && module_->asm_js()) { | 1162 if (module_ && module_->asm_js()) { |
| 1183 // asm.js must use the wacky JS semantics. | 1163 // asm.js must use the wacky JS semantics. |
| 1184 return graph()->NewNode( | 1164 return graph()->NewNode( |
| 1185 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); | 1165 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); |
| 1186 } | 1166 } |
| 1187 // Truncation of the input value is needed for the overflow check later. | 1167 // Truncation of the input value is needed for the overflow check later. |
| 1188 Node* trunc = Unop(wasm::kExprF64Trunc, input); | 1168 Node* trunc = Unop(wasm::kExprF64Trunc, input); |
| 1189 Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc); | 1169 Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc); |
| 1190 | 1170 |
| 1191 // Convert the result back to f64. If we end up at a different value than the | 1171 // Convert the result back to f64. If we end up at a different value than the |
| 1192 // truncated input value, then there has been an overflow and we trap. | 1172 // truncated input value, then there has been an overflow and we trap. |
| 1193 Node* check = Unop(wasm::kExprF64SConvertI32, result); | 1173 Node* check = Unop(wasm::kExprF64SConvertI32, result); |
| 1194 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); | 1174 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); |
| 1195 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1175 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); |
| 1196 | 1176 |
| 1197 return result; | 1177 return result; |
| 1198 } | 1178 } |
| 1199 | 1179 |
| 1200 | 1180 |
| 1201 Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input) { | 1181 Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input) { |
| 1202 MachineOperatorBuilder* m = jsgraph()->machine(); | 1182 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1203 if (module_ && module_->asm_js()) { | 1183 if (module_ && module_->asm_js()) { |
| 1204 // asm.js must use the wacky JS semantics. | 1184 // asm.js must use the wacky JS semantics. |
| 1205 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input); | 1185 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input); |
| 1206 return graph()->NewNode( | 1186 return graph()->NewNode( |
| 1207 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); | 1187 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); |
| 1208 } | 1188 } |
| 1209 | 1189 |
| 1210 // Truncation of the input value is needed for the overflow check later. | 1190 // Truncation of the input value is needed for the overflow check later. |
| 1211 Node* trunc = Unop(wasm::kExprF32Trunc, input); | 1191 Node* trunc = Unop(wasm::kExprF32Trunc, input); |
| 1212 Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc); | 1192 Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc); |
| 1213 | 1193 |
| 1214 // Convert the result back to f32. If we end up at a different value than the | 1194 // Convert the result back to f32. If we end up at a different value than the |
| 1215 // truncated input value, then there has been an overflow and we trap. | 1195 // truncated input value, then there has been an overflow and we trap. |
| 1216 Node* check = Unop(wasm::kExprF32UConvertI32, result); | 1196 Node* check = Unop(wasm::kExprF32UConvertI32, result); |
| 1217 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); | 1197 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); |
| 1218 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1198 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); |
| 1219 | 1199 |
| 1220 return result; | 1200 return result; |
| 1221 } | 1201 } |
| 1222 | 1202 |
| 1223 | 1203 |
| 1224 Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) { | 1204 Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) { |
| 1225 MachineOperatorBuilder* m = jsgraph()->machine(); | 1205 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1226 if (module_ && module_->asm_js()) { | 1206 if (module_ && module_->asm_js()) { |
| 1227 // asm.js must use the wacky JS semantics. | 1207 // asm.js must use the wacky JS semantics. |
| 1228 return graph()->NewNode( | 1208 return graph()->NewNode( |
| 1229 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); | 1209 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); |
| 1230 } | 1210 } |
| 1231 // Truncation of the input value is needed for the overflow check later. | 1211 // Truncation of the input value is needed for the overflow check later. |
| 1232 Node* trunc = Unop(wasm::kExprF64Trunc, input); | 1212 Node* trunc = Unop(wasm::kExprF64Trunc, input); |
| 1233 Node* result = graph()->NewNode(m->TruncateFloat64ToUint32(), trunc); | 1213 Node* result = graph()->NewNode(m->TruncateFloat64ToUint32(), trunc); |
| 1234 | 1214 |
| 1235 // Convert the result back to f64. If we end up at a different value than the | 1215 // Convert the result back to f64. If we end up at a different value than the |
| 1236 // truncated input value, then there has been an overflow and we trap. | 1216 // truncated input value, then there has been an overflow and we trap. |
| 1237 Node* check = Unop(wasm::kExprF64UConvertI32, result); | 1217 Node* check = Unop(wasm::kExprF64UConvertI32, result); |
| 1238 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); | 1218 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); |
| 1239 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1219 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); |
| 1240 | 1220 |
| 1241 return result; | 1221 return result; |
| 1242 } | 1222 } |
| 1243 | 1223 |
| 1244 | 1224 |
| 1245 Node* WasmGraphBuilder::BuildI32Ctz(Node* input) { | 1225 Node* WasmGraphBuilder::BuildI32Ctz(Node* input) { |
| 1246 //// Implement the following code as TF graph. | 1226 //// Implement the following code as TF graph. |
| 1247 // value = value | (value << 1); | 1227 // value = value | (value << 1); |
| 1248 // value = value | (value << 2); | 1228 // value = value | (value << 2); |
| 1249 // value = value | (value << 4); | 1229 // value = value | (value << 4); |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1659 if (jsgraph()->machine()->Is32()) { | 1639 if (jsgraph()->machine()->Is32()) { |
| 1660 return BuildFloatToIntConversionInstruction( | 1640 return BuildFloatToIntConversionInstruction( |
| 1661 input, ExternalReference::wasm_float32_to_int64(jsgraph()->isolate()), | 1641 input, ExternalReference::wasm_float32_to_int64(jsgraph()->isolate()), |
| 1662 MachineRepresentation::kFloat32, MachineType::Int64()); | 1642 MachineRepresentation::kFloat32, MachineType::Int64()); |
| 1663 } else { | 1643 } else { |
| 1664 Node* trunc = graph()->NewNode( | 1644 Node* trunc = graph()->NewNode( |
| 1665 jsgraph()->machine()->TryTruncateFloat32ToInt64(), input); | 1645 jsgraph()->machine()->TryTruncateFloat32ToInt64(), input); |
| 1666 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1646 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
| 1667 Node* overflow = | 1647 Node* overflow = |
| 1668 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1648 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
| 1669 trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow); | 1649 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); |
| 1670 return result; | 1650 return result; |
| 1671 } | 1651 } |
| 1672 } | 1652 } |
| 1673 | 1653 |
| 1674 Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input) { | 1654 Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input) { |
| 1675 if (jsgraph()->machine()->Is32()) { | 1655 if (jsgraph()->machine()->Is32()) { |
| 1676 return BuildFloatToIntConversionInstruction( | 1656 return BuildFloatToIntConversionInstruction( |
| 1677 input, ExternalReference::wasm_float32_to_uint64(jsgraph()->isolate()), | 1657 input, ExternalReference::wasm_float32_to_uint64(jsgraph()->isolate()), |
| 1678 MachineRepresentation::kFloat32, MachineType::Int64()); | 1658 MachineRepresentation::kFloat32, MachineType::Int64()); |
| 1679 } else { | 1659 } else { |
| 1680 Node* trunc = graph()->NewNode( | 1660 Node* trunc = graph()->NewNode( |
| 1681 jsgraph()->machine()->TryTruncateFloat32ToUint64(), input); | 1661 jsgraph()->machine()->TryTruncateFloat32ToUint64(), input); |
| 1682 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1662 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
| 1683 Node* overflow = | 1663 Node* overflow = |
| 1684 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1664 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
| 1685 trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow); | 1665 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); |
| 1686 return result; | 1666 return result; |
| 1687 } | 1667 } |
| 1688 } | 1668 } |
| 1689 | 1669 |
| 1690 Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input) { | 1670 Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input) { |
| 1691 if (jsgraph()->machine()->Is32()) { | 1671 if (jsgraph()->machine()->Is32()) { |
| 1692 return BuildFloatToIntConversionInstruction( | 1672 return BuildFloatToIntConversionInstruction( |
| 1693 input, ExternalReference::wasm_float64_to_int64(jsgraph()->isolate()), | 1673 input, ExternalReference::wasm_float64_to_int64(jsgraph()->isolate()), |
| 1694 MachineRepresentation::kFloat64, MachineType::Int64()); | 1674 MachineRepresentation::kFloat64, MachineType::Int64()); |
| 1695 } else { | 1675 } else { |
| 1696 Node* trunc = graph()->NewNode( | 1676 Node* trunc = graph()->NewNode( |
| 1697 jsgraph()->machine()->TryTruncateFloat64ToInt64(), input); | 1677 jsgraph()->machine()->TryTruncateFloat64ToInt64(), input); |
| 1698 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1678 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
| 1699 Node* overflow = | 1679 Node* overflow = |
| 1700 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1680 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
| 1701 trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow); | 1681 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); |
| 1702 return result; | 1682 return result; |
| 1703 } | 1683 } |
| 1704 } | 1684 } |
| 1705 | 1685 |
| 1706 Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input) { | 1686 Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input) { |
| 1707 if (jsgraph()->machine()->Is32()) { | 1687 if (jsgraph()->machine()->Is32()) { |
| 1708 return BuildFloatToIntConversionInstruction( | 1688 return BuildFloatToIntConversionInstruction( |
| 1709 input, ExternalReference::wasm_float64_to_uint64(jsgraph()->isolate()), | 1689 input, ExternalReference::wasm_float64_to_uint64(jsgraph()->isolate()), |
| 1710 MachineRepresentation::kFloat64, MachineType::Int64()); | 1690 MachineRepresentation::kFloat64, MachineType::Int64()); |
| 1711 } else { | 1691 } else { |
| 1712 Node* trunc = graph()->NewNode( | 1692 Node* trunc = graph()->NewNode( |
| 1713 jsgraph()->machine()->TryTruncateFloat64ToUint64(), input); | 1693 jsgraph()->machine()->TryTruncateFloat64ToUint64(), input); |
| 1714 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1694 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
| 1715 Node* overflow = | 1695 Node* overflow = |
| 1716 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1696 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
| 1717 trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow); | 1697 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); |
| 1718 return result; | 1698 return result; |
| 1719 } | 1699 } |
| 1720 } | 1700 } |
| 1721 | 1701 |
| 1722 Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction( | 1702 Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction( |
| 1723 Node* input, ExternalReference ref, | 1703 Node* input, ExternalReference ref, |
| 1724 MachineRepresentation parameter_representation, | 1704 MachineRepresentation parameter_representation, |
| 1725 const MachineType result_type) { | 1705 const MachineType result_type) { |
| 1726 Node* stack_slot_param = graph()->NewNode( | 1706 Node* stack_slot_param = graph()->NewNode( |
| 1727 jsgraph()->machine()->StackSlot(parameter_representation)); | 1707 jsgraph()->machine()->StackSlot(parameter_representation)); |
| 1728 Node* stack_slot_result = graph()->NewNode( | 1708 Node* stack_slot_result = graph()->NewNode( |
| 1729 jsgraph()->machine()->StackSlot(result_type.representation())); | 1709 jsgraph()->machine()->StackSlot(result_type.representation())); |
| 1730 const Operator* store_op = jsgraph()->machine()->Store( | 1710 const Operator* store_op = jsgraph()->machine()->Store( |
| 1731 StoreRepresentation(parameter_representation, kNoWriteBarrier)); | 1711 StoreRepresentation(parameter_representation, kNoWriteBarrier)); |
| 1732 *effect_ = | 1712 *effect_ = |
| 1733 graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), | 1713 graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), |
| 1734 input, *effect_, *control_); | 1714 input, *effect_, *control_); |
| 1735 MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); | 1715 MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); |
| 1736 sig_builder.AddReturn(MachineType::Int32()); | 1716 sig_builder.AddReturn(MachineType::Int32()); |
| 1737 sig_builder.AddParam(MachineType::Pointer()); | 1717 sig_builder.AddParam(MachineType::Pointer()); |
| 1738 sig_builder.AddParam(MachineType::Pointer()); | 1718 sig_builder.AddParam(MachineType::Pointer()); |
| 1739 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); | 1719 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); |
| 1740 Node* args[] = {function, stack_slot_param, stack_slot_result}; | 1720 Node* args[] = {function, stack_slot_param, stack_slot_result}; |
| 1741 trap_->ZeroCheck32(kTrapFloatUnrepresentable, | 1721 trap_->ZeroCheck32(wasm::kTrapFloatUnrepresentable, |
| 1742 BuildCCall(sig_builder.Build(), args)); | 1722 BuildCCall(sig_builder.Build(), args)); |
| 1743 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1723 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
| 1744 Node* load = | 1724 Node* load = |
| 1745 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), | 1725 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), |
| 1746 *effect_, *control_); | 1726 *effect_, *control_); |
| 1747 *effect_ = load; | 1727 *effect_ = load; |
| 1748 return load; | 1728 return load; |
| 1749 } | 1729 } |
| 1750 | 1730 |
| 1751 Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right) { | 1731 Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1771 | 1751 |
| 1772 Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false); | 1752 Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false); |
| 1773 Node* neg = | 1753 Node* neg = |
| 1774 graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left); | 1754 graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left); |
| 1775 | 1755 |
| 1776 return n.Phi(MachineRepresentation::kWord32, neg, | 1756 return n.Phi(MachineRepresentation::kWord32, neg, |
| 1777 z.Phi(MachineRepresentation::kWord32, | 1757 z.Phi(MachineRepresentation::kWord32, |
| 1778 jsgraph()->Int32Constant(0), div)); | 1758 jsgraph()->Int32Constant(0), div)); |
| 1779 } | 1759 } |
| 1780 | 1760 |
| 1781 trap_->ZeroCheck32(kTrapDivByZero, right); | 1761 trap_->ZeroCheck32(wasm::kTrapDivByZero, right); |
| 1782 Node* before = *control_; | 1762 Node* before = *control_; |
| 1783 Node* denom_is_m1; | 1763 Node* denom_is_m1; |
| 1784 Node* denom_is_not_m1; | 1764 Node* denom_is_not_m1; |
| 1785 Branch( | 1765 Branch( |
| 1786 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | 1766 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
| 1787 &denom_is_m1, &denom_is_not_m1); | 1767 &denom_is_m1, &denom_is_not_m1); |
| 1788 *control_ = denom_is_m1; | 1768 *control_ = denom_is_m1; |
| 1789 trap_->TrapIfEq32(kTrapDivUnrepresentable, left, kMinInt); | 1769 trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, left, kMinInt); |
| 1790 if (*control_ != denom_is_m1) { | 1770 if (*control_ != denom_is_m1) { |
| 1791 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, | 1771 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, |
| 1792 *control_); | 1772 *control_); |
| 1793 } else { | 1773 } else { |
| 1794 *control_ = before; | 1774 *control_ = before; |
| 1795 } | 1775 } |
| 1796 return graph()->NewNode(m->Int32Div(), left, right, *control_); | 1776 return graph()->NewNode(m->Int32Div(), left, right, *control_); |
| 1797 } | 1777 } |
| 1798 | 1778 |
| 1799 Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right) { | 1779 Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1812 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | 1792 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
| 1813 BranchHint::kFalse); | 1793 BranchHint::kFalse); |
| 1814 d.Chain(z.if_false); | 1794 d.Chain(z.if_false); |
| 1815 | 1795 |
| 1816 return z.Phi( | 1796 return z.Phi( |
| 1817 MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1797 MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
| 1818 d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1798 d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
| 1819 graph()->NewNode(m->Int32Mod(), left, right, d.if_false))); | 1799 graph()->NewNode(m->Int32Mod(), left, right, d.if_false))); |
| 1820 } | 1800 } |
| 1821 | 1801 |
| 1822 trap_->ZeroCheck32(kTrapRemByZero, right); | 1802 trap_->ZeroCheck32(wasm::kTrapRemByZero, right); |
| 1823 | 1803 |
| 1824 Diamond d( | 1804 Diamond d( |
| 1825 graph(), jsgraph()->common(), | 1805 graph(), jsgraph()->common(), |
| 1826 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | 1806 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
| 1827 BranchHint::kFalse); | 1807 BranchHint::kFalse); |
| 1828 d.Chain(*control_); | 1808 d.Chain(*control_); |
| 1829 | 1809 |
| 1830 return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1810 return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
| 1831 graph()->NewNode(m->Int32Mod(), left, right, d.if_false)); | 1811 graph()->NewNode(m->Int32Mod(), left, right, d.if_false)); |
| 1832 } | 1812 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1844 Diamond z( | 1824 Diamond z( |
| 1845 graph(), jsgraph()->common(), | 1825 graph(), jsgraph()->common(), |
| 1846 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | 1826 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
| 1847 BranchHint::kFalse); | 1827 BranchHint::kFalse); |
| 1848 | 1828 |
| 1849 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1829 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
| 1850 graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, | 1830 graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, |
| 1851 right, z.if_false)); | 1831 right, z.if_false)); |
| 1852 } | 1832 } |
| 1853 return graph()->NewNode(m->Uint32Div(), left, right, | 1833 return graph()->NewNode(m->Uint32Div(), left, right, |
| 1854 trap_->ZeroCheck32(kTrapDivByZero, right)); | 1834 trap_->ZeroCheck32(wasm::kTrapDivByZero, right)); |
| 1855 } | 1835 } |
| 1856 | 1836 |
| 1857 Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right) { | 1837 Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right) { |
| 1858 MachineOperatorBuilder* m = jsgraph()->machine(); | 1838 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1859 if (module_ && module_->asm_js()) { | 1839 if (module_ && module_->asm_js()) { |
| 1860 // asm.js semantics return 0 on divide or mod by zero. | 1840 // asm.js semantics return 0 on divide or mod by zero. |
| 1861 // Explicit check for x % 0. | 1841 // Explicit check for x % 0. |
| 1862 Diamond z( | 1842 Diamond z( |
| 1863 graph(), jsgraph()->common(), | 1843 graph(), jsgraph()->common(), |
| 1864 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | 1844 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
| 1865 BranchHint::kFalse); | 1845 BranchHint::kFalse); |
| 1866 | 1846 |
| 1867 Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right, | 1847 Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right, |
| 1868 z.if_false); | 1848 z.if_false); |
| 1869 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1849 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
| 1870 rem); | 1850 rem); |
| 1871 } | 1851 } |
| 1872 | 1852 |
| 1873 return graph()->NewNode(m->Uint32Mod(), left, right, | 1853 return graph()->NewNode(m->Uint32Mod(), left, right, |
| 1874 trap_->ZeroCheck32(kTrapRemByZero, right)); | 1854 trap_->ZeroCheck32(wasm::kTrapRemByZero, right)); |
| 1875 } | 1855 } |
| 1876 | 1856 |
| 1877 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { | 1857 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { |
| 1878 if (jsgraph()->machine()->Is32()) { | 1858 if (jsgraph()->machine()->Is32()) { |
| 1879 return BuildDiv64Call( | 1859 return BuildDiv64Call( |
| 1880 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), | 1860 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), |
| 1881 MachineType::Int64(), kTrapDivByZero); | 1861 MachineType::Int64(), wasm::kTrapDivByZero); |
| 1882 } | 1862 } |
| 1883 trap_->ZeroCheck64(kTrapDivByZero, right); | 1863 trap_->ZeroCheck64(wasm::kTrapDivByZero, right); |
| 1884 Node* before = *control_; | 1864 Node* before = *control_; |
| 1885 Node* denom_is_m1; | 1865 Node* denom_is_m1; |
| 1886 Node* denom_is_not_m1; | 1866 Node* denom_is_not_m1; |
| 1887 Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, | 1867 Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
| 1888 jsgraph()->Int64Constant(-1)), | 1868 jsgraph()->Int64Constant(-1)), |
| 1889 &denom_is_m1, &denom_is_not_m1); | 1869 &denom_is_m1, &denom_is_not_m1); |
| 1890 *control_ = denom_is_m1; | 1870 *control_ = denom_is_m1; |
| 1891 trap_->TrapIfEq64(kTrapDivUnrepresentable, left, | 1871 trap_->TrapIfEq64(wasm::kTrapDivUnrepresentable, left, |
| 1892 std::numeric_limits<int64_t>::min()); | 1872 std::numeric_limits<int64_t>::min()); |
| 1893 if (*control_ != denom_is_m1) { | 1873 if (*control_ != denom_is_m1) { |
| 1894 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, | 1874 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, |
| 1895 *control_); | 1875 *control_); |
| 1896 } else { | 1876 } else { |
| 1897 *control_ = before; | 1877 *control_ = before; |
| 1898 } | 1878 } |
| 1899 return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right, | 1879 return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right, |
| 1900 *control_); | 1880 *control_); |
| 1901 } | 1881 } |
| 1902 | 1882 |
| 1903 Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right) { | 1883 Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right) { |
| 1904 if (jsgraph()->machine()->Is32()) { | 1884 if (jsgraph()->machine()->Is32()) { |
| 1905 return BuildDiv64Call( | 1885 return BuildDiv64Call( |
| 1906 left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()), | 1886 left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()), |
| 1907 MachineType::Int64(), kTrapRemByZero); | 1887 MachineType::Int64(), wasm::kTrapRemByZero); |
| 1908 } | 1888 } |
| 1909 trap_->ZeroCheck64(kTrapRemByZero, right); | 1889 trap_->ZeroCheck64(wasm::kTrapRemByZero, right); |
| 1910 Diamond d(jsgraph()->graph(), jsgraph()->common(), | 1890 Diamond d(jsgraph()->graph(), jsgraph()->common(), |
| 1911 graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, | 1891 graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
| 1912 jsgraph()->Int64Constant(-1))); | 1892 jsgraph()->Int64Constant(-1))); |
| 1913 | 1893 |
| 1914 Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right, | 1894 Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right, |
| 1915 d.if_false); | 1895 d.if_false); |
| 1916 | 1896 |
| 1917 return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), | 1897 return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), |
| 1918 rem); | 1898 rem); |
| 1919 } | 1899 } |
| 1920 | 1900 |
| 1921 Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right) { | 1901 Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right) { |
| 1922 if (jsgraph()->machine()->Is32()) { | 1902 if (jsgraph()->machine()->Is32()) { |
| 1923 return BuildDiv64Call( | 1903 return BuildDiv64Call( |
| 1924 left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()), | 1904 left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()), |
| 1925 MachineType::Int64(), kTrapDivByZero); | 1905 MachineType::Int64(), wasm::kTrapDivByZero); |
| 1926 } | 1906 } |
| 1927 return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right, | 1907 return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right, |
| 1928 trap_->ZeroCheck64(kTrapDivByZero, right)); | 1908 trap_->ZeroCheck64(wasm::kTrapDivByZero, right)); |
| 1929 } | 1909 } |
| 1930 Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right) { | 1910 Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right) { |
| 1931 if (jsgraph()->machine()->Is32()) { | 1911 if (jsgraph()->machine()->Is32()) { |
| 1932 return BuildDiv64Call( | 1912 return BuildDiv64Call( |
| 1933 left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()), | 1913 left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()), |
| 1934 MachineType::Int64(), kTrapRemByZero); | 1914 MachineType::Int64(), wasm::kTrapRemByZero); |
| 1935 } | 1915 } |
| 1936 return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right, | 1916 return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right, |
| 1937 trap_->ZeroCheck64(kTrapRemByZero, right)); | 1917 trap_->ZeroCheck64(wasm::kTrapRemByZero, right)); |
| 1938 } | 1918 } |
| 1939 | 1919 |
| 1940 Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right, | 1920 Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right, |
| 1941 ExternalReference ref, | 1921 ExternalReference ref, |
| 1942 MachineType result_type, int trap_zero) { | 1922 MachineType result_type, int trap_zero) { |
| 1943 Node* stack_slot_dst = graph()->NewNode( | 1923 Node* stack_slot_dst = graph()->NewNode( |
| 1944 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); | 1924 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); |
| 1945 Node* stack_slot_src = graph()->NewNode( | 1925 Node* stack_slot_src = graph()->NewNode( |
| 1946 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); | 1926 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); |
| 1947 | 1927 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1959 sig_builder.AddParam(MachineType::Pointer()); | 1939 sig_builder.AddParam(MachineType::Pointer()); |
| 1960 sig_builder.AddParam(MachineType::Pointer()); | 1940 sig_builder.AddParam(MachineType::Pointer()); |
| 1961 | 1941 |
| 1962 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); | 1942 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); |
| 1963 Node* args[] = {function, stack_slot_dst, stack_slot_src}; | 1943 Node* args[] = {function, stack_slot_dst, stack_slot_src}; |
| 1964 | 1944 |
| 1965 Node* call = BuildCCall(sig_builder.Build(), args); | 1945 Node* call = BuildCCall(sig_builder.Build(), args); |
| 1966 | 1946 |
| 1967 // TODO(wasm): This can get simpler if we have a specialized runtime call to | 1947 // TODO(wasm): This can get simpler if we have a specialized runtime call to |
| 1968 // throw WASM exceptions by trap code instead of by string. | 1948 // throw WASM exceptions by trap code instead of by string. |
| 1969 trap_->ZeroCheck32(static_cast<TrapReason>(trap_zero), call); | 1949 trap_->ZeroCheck32(static_cast<wasm::TrapReason>(trap_zero), call); |
| 1970 trap_->TrapIfEq32(kTrapDivUnrepresentable, call, -1); | 1950 trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, call, -1); |
| 1971 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1951 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
| 1972 Node* load = | 1952 Node* load = |
| 1973 graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0), | 1953 graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0), |
| 1974 *effect_, *control_); | 1954 *effect_, *control_); |
| 1975 *effect_ = load; | 1955 *effect_ = load; |
| 1976 return load; | 1956 return load; |
| 1977 } | 1957 } |
| 1978 | 1958 |
| 1979 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { | 1959 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { |
| 1980 const size_t params = sig->parameter_count(); | 1960 const size_t params = sig->parameter_count(); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2046 | 2026 |
| 2047 // Compute the code object by loading it from the function table. | 2027 // Compute the code object by loading it from the function table. |
| 2048 Node* key = args[0]; | 2028 Node* key = args[0]; |
| 2049 | 2029 |
| 2050 // Bounds check the index. | 2030 // Bounds check the index. |
| 2051 int table_size = static_cast<int>(module_->FunctionTableSize()); | 2031 int table_size = static_cast<int>(module_->FunctionTableSize()); |
| 2052 if (table_size > 0) { | 2032 if (table_size > 0) { |
| 2053 // Bounds check against the table size. | 2033 // Bounds check against the table size. |
| 2054 Node* size = Int32Constant(static_cast<int>(table_size)); | 2034 Node* size = Int32Constant(static_cast<int>(table_size)); |
| 2055 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); | 2035 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); |
| 2056 trap_->AddTrapIfFalse(kTrapFuncInvalid, in_bounds); | 2036 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds); |
| 2057 } else { | 2037 } else { |
| 2058 // No function table. Generate a trap and return a constant. | 2038 // No function table. Generate a trap and return a constant. |
| 2059 trap_->AddTrapIfFalse(kTrapFuncInvalid, Int32Constant(0)); | 2039 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0)); |
| 2060 return trap_->GetTrapValue(module_->GetSignature(index)); | 2040 return trap_->GetTrapValue(module_->GetSignature(index)); |
| 2061 } | 2041 } |
| 2062 Node* table = FunctionTable(); | 2042 Node* table = FunctionTable(); |
| 2063 | 2043 |
| 2064 // Load signature from the table and check. | 2044 // Load signature from the table and check. |
| 2065 // The table is a FixedArray; signatures are encoded as SMIs. | 2045 // The table is a FixedArray; signatures are encoded as SMIs. |
| 2066 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] | 2046 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] |
| 2067 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 2047 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
| 2068 const int fixed_offset = access.header_size - access.tag(); | 2048 const int fixed_offset = access.header_size - access.tag(); |
| 2069 { | 2049 { |
| 2070 Node* load_sig = graph()->NewNode( | 2050 Node* load_sig = graph()->NewNode( |
| 2071 machine->Load(MachineType::AnyTagged()), table, | 2051 machine->Load(MachineType::AnyTagged()), table, |
| 2072 graph()->NewNode(machine->Int32Add(), | 2052 graph()->NewNode(machine->Int32Add(), |
| 2073 graph()->NewNode(machine->Word32Shl(), key, | 2053 graph()->NewNode(machine->Word32Shl(), key, |
| 2074 Int32Constant(kPointerSizeLog2)), | 2054 Int32Constant(kPointerSizeLog2)), |
| 2075 Int32Constant(fixed_offset)), | 2055 Int32Constant(fixed_offset)), |
| 2076 *effect_, *control_); | 2056 *effect_, *control_); |
| 2077 Node* sig_match = graph()->NewNode(machine->WordEqual(), load_sig, | 2057 Node* sig_match = graph()->NewNode(machine->WordEqual(), load_sig, |
| 2078 jsgraph()->SmiConstant(index)); | 2058 jsgraph()->SmiConstant(index)); |
| 2079 trap_->AddTrapIfFalse(kTrapFuncSigMismatch, sig_match); | 2059 trap_->AddTrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match); |
| 2080 } | 2060 } |
| 2081 | 2061 |
| 2082 // Load code object from the table. | 2062 // Load code object from the table. |
| 2083 int offset = fixed_offset + kPointerSize * table_size; | 2063 int offset = fixed_offset + kPointerSize * table_size; |
| 2084 Node* load_code = graph()->NewNode( | 2064 Node* load_code = graph()->NewNode( |
| 2085 machine->Load(MachineType::AnyTagged()), table, | 2065 machine->Load(MachineType::AnyTagged()), table, |
| 2086 graph()->NewNode(machine->Int32Add(), | 2066 graph()->NewNode(machine->Int32Add(), |
| 2087 graph()->NewNode(machine->Word32Shl(), key, | 2067 graph()->NewNode(machine->Word32Shl(), key, |
| 2088 Int32Constant(kPointerSizeLog2)), | 2068 Int32Constant(kPointerSizeLog2)), |
| 2089 Int32Constant(offset)), | 2069 Int32Constant(offset)), |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2388 cond = jsgraph()->Int32Constant(0); | 2368 cond = jsgraph()->Int32Constant(0); |
| 2389 } else { | 2369 } else { |
| 2390 // Check against the limit. | 2370 // Check against the limit. |
| 2391 size_t limit = size - offset - memsize; | 2371 size_t limit = size - offset - memsize; |
| 2392 CHECK(limit <= kMaxUInt32); | 2372 CHECK(limit <= kMaxUInt32); |
| 2393 cond = graph()->NewNode( | 2373 cond = graph()->NewNode( |
| 2394 jsgraph()->machine()->Uint32LessThanOrEqual(), index, | 2374 jsgraph()->machine()->Uint32LessThanOrEqual(), index, |
| 2395 jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); | 2375 jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); |
| 2396 } | 2376 } |
| 2397 | 2377 |
| 2398 trap_->AddTrapIfFalse(kTrapMemOutOfBounds, cond); | 2378 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond); |
| 2399 } | 2379 } |
| 2400 | 2380 |
| 2401 | 2381 |
| 2402 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, | 2382 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, |
| 2403 Node* index, uint32_t offset) { | 2383 Node* index, uint32_t offset) { |
| 2404 Node* load; | 2384 Node* load; |
| 2405 | 2385 |
| 2406 if (module_ && module_->asm_js()) { | 2386 if (module_ && module_->asm_js()) { |
| 2407 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). | 2387 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). |
| 2408 DCHECK_EQ(0, offset); | 2388 DCHECK_EQ(0, offset); |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2798 static_cast<int>(function.code_end_offset - function.code_start_offset), | 2778 static_cast<int>(function.code_end_offset - function.code_start_offset), |
| 2799 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); | 2779 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); |
| 2800 } | 2780 } |
| 2801 return code; | 2781 return code; |
| 2802 } | 2782 } |
| 2803 | 2783 |
| 2804 | 2784 |
| 2805 } // namespace compiler | 2785 } // namespace compiler |
| 2806 } // namespace internal | 2786 } // namespace internal |
| 2807 } // namespace v8 | 2787 } // namespace v8 |
| OLD | NEW |