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 |