| 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/platform.h" | 9 #include "src/base/platform/platform.h" |
| 10 | 10 |
| (...skipping 1135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1146 wasm::kAstF64, right, | 1146 wasm::kAstF64, right, |
| 1147 left_is_not_nan.Phi( | 1147 left_is_not_nan.Phi( |
| 1148 wasm::kAstF64, | 1148 wasm::kAstF64, |
| 1149 Binop(wasm::kExprF64Mul, right, Float64Constant(1.0)), | 1149 Binop(wasm::kExprF64Mul, right, Float64Constant(1.0)), |
| 1150 Binop(wasm::kExprF64Mul, left, Float64Constant(1.0))))); | 1150 Binop(wasm::kExprF64Mul, left, Float64Constant(1.0))))); |
| 1151 } | 1151 } |
| 1152 | 1152 |
| 1153 | 1153 |
| 1154 Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input) { | 1154 Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input) { |
| 1155 MachineOperatorBuilder* m = jsgraph()->machine(); | 1155 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1156 if (module_ && module_->asm_js()) { |
| 1157 // asm.js must use the wacky JS semantics. |
| 1158 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input); |
| 1159 return graph()->NewNode( |
| 1160 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); |
| 1161 } |
| 1162 |
| 1156 // Truncation of the input value is needed for the overflow check later. | 1163 // Truncation of the input value is needed for the overflow check later. |
| 1157 Node* trunc = Unop(wasm::kExprF32Trunc, input); | 1164 Node* trunc = Unop(wasm::kExprF32Trunc, input); |
| 1158 Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc); | 1165 Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc); |
| 1159 | 1166 |
| 1160 // Convert the result back to f64. If we end up at a different value than the | 1167 // Convert the result back to f64. If we end up at a different value than the |
| 1161 // truncated input value, then there has been an overflow and we trap. | 1168 // truncated input value, then there has been an overflow and we trap. |
| 1162 Node* check = Unop(wasm::kExprF32SConvertI32, result); | 1169 Node* check = Unop(wasm::kExprF32SConvertI32, result); |
| 1163 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); | 1170 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); |
| 1164 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1171 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); |
| 1165 | 1172 |
| 1166 return result; | 1173 return result; |
| 1167 } | 1174 } |
| 1168 | 1175 |
| 1169 | 1176 |
| 1170 Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) { | 1177 Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) { |
| 1171 MachineOperatorBuilder* m = jsgraph()->machine(); | 1178 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1172 if (module_ && module_->asm_js) { | 1179 if (module_ && module_->asm_js()) { |
| 1180 // asm.js must use the wacky JS semantics. |
| 1173 return graph()->NewNode( | 1181 return graph()->NewNode( |
| 1174 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); | 1182 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); |
| 1175 } | 1183 } |
| 1176 // Truncation of the input value is needed for the overflow check later. | 1184 // Truncation of the input value is needed for the overflow check later. |
| 1177 Node* trunc = Unop(wasm::kExprF64Trunc, input); | 1185 Node* trunc = Unop(wasm::kExprF64Trunc, input); |
| 1178 Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc); | 1186 Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc); |
| 1179 | 1187 |
| 1180 // Convert the result back to f64. If we end up at a different value than the | 1188 // Convert the result back to f64. If we end up at a different value than the |
| 1181 // truncated input value, then there has been an overflow and we trap. | 1189 // truncated input value, then there has been an overflow and we trap. |
| 1182 Node* check = Unop(wasm::kExprF64SConvertI32, result); | 1190 Node* check = Unop(wasm::kExprF64SConvertI32, result); |
| 1183 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); | 1191 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); |
| 1184 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1192 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); |
| 1185 | 1193 |
| 1186 return result; | 1194 return result; |
| 1187 } | 1195 } |
| 1188 | 1196 |
| 1189 | 1197 |
| 1190 Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input) { | 1198 Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input) { |
| 1191 MachineOperatorBuilder* m = jsgraph()->machine(); | 1199 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1200 if (module_ && module_->asm_js()) { |
| 1201 // asm.js must use the wacky JS semantics. |
| 1202 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input); |
| 1203 return graph()->NewNode( |
| 1204 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); |
| 1205 } |
| 1206 |
| 1192 // Truncation of the input value is needed for the overflow check later. | 1207 // Truncation of the input value is needed for the overflow check later. |
| 1193 Node* trunc = Unop(wasm::kExprF32Trunc, input); | 1208 Node* trunc = Unop(wasm::kExprF32Trunc, input); |
| 1194 Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc); | 1209 Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc); |
| 1195 | 1210 |
| 1196 // Convert the result back to f32. If we end up at a different value than the | 1211 // Convert the result back to f32. If we end up at a different value than the |
| 1197 // truncated input value, then there has been an overflow and we trap. | 1212 // truncated input value, then there has been an overflow and we trap. |
| 1198 Node* check = Unop(wasm::kExprF32UConvertI32, result); | 1213 Node* check = Unop(wasm::kExprF32UConvertI32, result); |
| 1199 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); | 1214 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); |
| 1200 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1215 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); |
| 1201 | 1216 |
| 1202 return result; | 1217 return result; |
| 1203 } | 1218 } |
| 1204 | 1219 |
| 1205 | 1220 |
| 1206 Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) { | 1221 Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) { |
| 1207 MachineOperatorBuilder* m = jsgraph()->machine(); | 1222 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1208 if (module_ && module_->asm_js) { | 1223 if (module_ && module_->asm_js()) { |
| 1224 // asm.js must use the wacky JS semantics. |
| 1209 return graph()->NewNode( | 1225 return graph()->NewNode( |
| 1210 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); | 1226 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); |
| 1211 } | 1227 } |
| 1212 // Truncation of the input value is needed for the overflow check later. | 1228 // Truncation of the input value is needed for the overflow check later. |
| 1213 Node* trunc = Unop(wasm::kExprF64Trunc, input); | 1229 Node* trunc = Unop(wasm::kExprF64Trunc, input); |
| 1214 Node* result = graph()->NewNode(m->ChangeFloat64ToUint32(), trunc); | 1230 Node* result = graph()->NewNode(m->ChangeFloat64ToUint32(), trunc); |
| 1215 | 1231 |
| 1216 // Convert the result back to f64. If we end up at a different value than the | 1232 // Convert the result back to f64. If we end up at a different value than the |
| 1217 // truncated input value, then there has been an overflow and we trap. | 1233 // truncated input value, then there has been an overflow and we trap. |
| 1218 Node* check = Unop(wasm::kExprF64UConvertI32, result); | 1234 Node* check = Unop(wasm::kExprF64UConvertI32, result); |
| (...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1882 } | 1898 } |
| 1883 | 1899 |
| 1884 trap_->AddTrapIfFalse(kTrapMemOutOfBounds, cond); | 1900 trap_->AddTrapIfFalse(kTrapMemOutOfBounds, cond); |
| 1885 } | 1901 } |
| 1886 | 1902 |
| 1887 | 1903 |
| 1888 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, | 1904 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, |
| 1889 Node* index, uint32_t offset) { | 1905 Node* index, uint32_t offset) { |
| 1890 Node* load; | 1906 Node* load; |
| 1891 | 1907 |
| 1892 if (module_ && module_->asm_js) { | 1908 if (module_ && module_->asm_js()) { |
| 1893 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). | 1909 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). |
| 1894 DCHECK_EQ(0, offset); | 1910 DCHECK_EQ(0, offset); |
| 1895 const Operator* op = jsgraph()->machine()->CheckedLoad(memtype); | 1911 const Operator* op = jsgraph()->machine()->CheckedLoad(memtype); |
| 1896 load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_, | 1912 load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_, |
| 1897 *control_); | 1913 *control_); |
| 1898 } else { | 1914 } else { |
| 1899 // WASM semantics throw on OOB. Introduce explicit bounds check. | 1915 // WASM semantics throw on OOB. Introduce explicit bounds check. |
| 1900 BoundsCheckMem(memtype, index, offset); | 1916 BoundsCheckMem(memtype, index, offset); |
| 1901 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), | 1917 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |
| 1902 MemBuffer(offset), index, *effect_, *control_); | 1918 MemBuffer(offset), index, *effect_, *control_); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1917 } | 1933 } |
| 1918 } | 1934 } |
| 1919 | 1935 |
| 1920 return load; | 1936 return load; |
| 1921 } | 1937 } |
| 1922 | 1938 |
| 1923 | 1939 |
| 1924 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, | 1940 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |
| 1925 uint32_t offset, Node* val) { | 1941 uint32_t offset, Node* val) { |
| 1926 Node* store; | 1942 Node* store; |
| 1927 if (module_ && module_->asm_js) { | 1943 if (module_ && module_->asm_js()) { |
| 1928 // asm.js semantics use CheckedStore (i.e. ignore OOB writes). | 1944 // asm.js semantics use CheckedStore (i.e. ignore OOB writes). |
| 1929 DCHECK_EQ(0, offset); | 1945 DCHECK_EQ(0, offset); |
| 1930 const Operator* op = | 1946 const Operator* op = |
| 1931 jsgraph()->machine()->CheckedStore(memtype.representation()); | 1947 jsgraph()->machine()->CheckedStore(memtype.representation()); |
| 1932 store = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), val, *effect_, | 1948 store = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), val, *effect_, |
| 1933 *control_); | 1949 *control_); |
| 1934 } else { | 1950 } else { |
| 1935 // WASM semantics throw on OOB. Introduce explicit bounds check. | 1951 // WASM semantics throw on OOB. Introduce explicit bounds check. |
| 1936 BoundsCheckMem(memtype, index, offset); | 1952 BoundsCheckMem(memtype, index, offset); |
| 1937 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 1953 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2247 module_env->module->GetName(function.name_offset)); | 2263 module_env->module->GetName(function.name_offset)); |
| 2248 } | 2264 } |
| 2249 | 2265 |
| 2250 return code; | 2266 return code; |
| 2251 } | 2267 } |
| 2252 | 2268 |
| 2253 | 2269 |
| 2254 } // namespace compiler | 2270 } // namespace compiler |
| 2255 } // namespace internal | 2271 } // namespace internal |
| 2256 } // namespace v8 | 2272 } // namespace v8 |
| OLD | NEW |