| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/wasm-compiler.h" | 5 #include "src/compiler/wasm-compiler.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/isolate-inl.h" | 9 #include "src/isolate-inl.h" |
| 10 | 10 |
| (...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1000 int64_t masked = (match.Value() & kMask64); | 1000 int64_t masked = (match.Value() & kMask64); |
| 1001 if (match.Value() != masked) node = jsgraph()->Int64Constant(masked); | 1001 if (match.Value() != masked) node = jsgraph()->Int64Constant(masked); |
| 1002 } else { | 1002 } else { |
| 1003 node = graph()->NewNode(jsgraph()->machine()->Word64And(), node, | 1003 node = graph()->NewNode(jsgraph()->machine()->Word64And(), node, |
| 1004 jsgraph()->Int64Constant(kMask64)); | 1004 jsgraph()->Int64Constant(kMask64)); |
| 1005 } | 1005 } |
| 1006 } | 1006 } |
| 1007 return node; | 1007 return node; |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 static bool ReverseBytesSupported(MachineOperatorBuilder* m, |
| 1011 size_t size_in_bytes) { |
| 1012 switch (size_in_bytes) { |
| 1013 case 4: |
| 1014 return m->Word32ReverseBytes().IsSupported(); |
| 1015 case 8: |
| 1016 return m->Word64ReverseBytes().IsSupported(); |
| 1017 default: |
| 1018 break; |
| 1019 } |
| 1020 return false; |
| 1021 } |
| 1022 |
| 1010 Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype, | 1023 Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype, |
| 1011 wasm::LocalType wasmtype) { | 1024 wasm::LocalType wasmtype) { |
| 1012 Node* result; | 1025 Node* result; |
| 1013 Node* value = node; | 1026 Node* value = node; |
| 1014 const Operator* shiftLeftOpcode; | |
| 1015 const Operator* shiftRightOpcode; | |
| 1016 const Operator* andOpcode; | |
| 1017 const Operator* orOpcode; | |
| 1018 MachineOperatorBuilder* m = jsgraph()->machine(); | 1027 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1019 int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation()); | 1028 int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation()); |
| 1020 int valueSizeInBits = 8 * valueSizeInBytes; | 1029 int valueSizeInBits = 8 * valueSizeInBytes; |
| 1021 bool isFloat = false; | 1030 bool isFloat = false; |
| 1022 | 1031 |
| 1023 switch (memtype.representation()) { | 1032 switch (memtype.representation()) { |
| 1024 case MachineRepresentation::kFloat64: | 1033 case MachineRepresentation::kFloat64: |
| 1025 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node); | 1034 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node); |
| 1026 isFloat = true; | 1035 isFloat = true; |
| 1027 case MachineRepresentation::kWord64: | 1036 case MachineRepresentation::kWord64: |
| 1028 shiftLeftOpcode = m->Word64Shl(); | |
| 1029 shiftRightOpcode = m->Word64Shr(); | |
| 1030 andOpcode = m->Word64And(); | |
| 1031 orOpcode = m->Word64Or(); | |
| 1032 result = jsgraph()->Int64Constant(0); | 1037 result = jsgraph()->Int64Constant(0); |
| 1033 break; | 1038 break; |
| 1034 case MachineRepresentation::kFloat32: | 1039 case MachineRepresentation::kFloat32: |
| 1035 value = graph()->NewNode(m->BitcastFloat32ToInt32(), node); | 1040 value = graph()->NewNode(m->BitcastFloat32ToInt32(), node); |
| 1036 isFloat = true; | 1041 isFloat = true; |
| 1037 case MachineRepresentation::kWord32: | 1042 case MachineRepresentation::kWord32: |
| 1038 case MachineRepresentation::kWord16: | 1043 case MachineRepresentation::kWord16: |
| 1039 shiftLeftOpcode = m->Word32Shl(); | |
| 1040 shiftRightOpcode = m->Word32Shr(); | |
| 1041 andOpcode = m->Word32And(); | |
| 1042 orOpcode = m->Word32Or(); | |
| 1043 result = jsgraph()->Int32Constant(0); | 1044 result = jsgraph()->Int32Constant(0); |
| 1044 break; | 1045 break; |
| 1045 case MachineRepresentation::kWord8: | 1046 case MachineRepresentation::kWord8: |
| 1046 // No need to change endianness for byte size, return original node | 1047 // No need to change endianness for byte size, return original node |
| 1047 return node; | 1048 return node; |
| 1048 break; | 1049 break; |
| 1049 default: | 1050 default: |
| 1050 UNREACHABLE(); | 1051 UNREACHABLE(); |
| 1051 break; | 1052 break; |
| 1052 } | 1053 } |
| 1053 | 1054 |
| 1054 int i; | 1055 int i; |
| 1055 uint32_t shiftCount; | 1056 uint32_t shiftCount; |
| 1056 | 1057 |
| 1057 for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2; | 1058 if (ReverseBytesSupported(m, valueSizeInBytes < 4 ? 4 : valueSizeInBytes)) { |
| 1058 i += 8, shiftCount -= 16) { | 1059 switch (valueSizeInBytes) { |
| 1059 Node* shiftLower; | 1060 case 2: |
| 1060 Node* shiftHigher; | 1061 result = |
| 1061 Node* lowerByte; | 1062 graph()->NewNode(m->Word32ReverseBytes().op(), |
| 1062 Node* higherByte; | 1063 graph()->NewNode(m->Word32Shl(), value, |
| 1064 jsgraph()->Int32Constant(16))); |
| 1065 break; |
| 1066 case 4: |
| 1067 result = graph()->NewNode(m->Word32ReverseBytes().op(), value); |
| 1068 break; |
| 1069 case 8: |
| 1070 result = graph()->NewNode(m->Word64ReverseBytes().op(), value); |
| 1071 break; |
| 1072 default: |
| 1073 UNREACHABLE(); |
| 1074 } |
| 1075 } else { |
| 1076 for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2; |
| 1077 i += 8, shiftCount -= 16) { |
| 1078 Node* shiftLower; |
| 1079 Node* shiftHigher; |
| 1080 Node* lowerByte; |
| 1081 Node* higherByte; |
| 1063 | 1082 |
| 1064 DCHECK(shiftCount > 0); | 1083 DCHECK(shiftCount > 0); |
| 1065 DCHECK((shiftCount + 8) % 16 == 0); | 1084 DCHECK((shiftCount + 8) % 16 == 0); |
| 1066 | 1085 |
| 1067 if (valueSizeInBits > 32) { | 1086 if (valueSizeInBits > 32) { |
| 1068 shiftLower = graph()->NewNode(shiftLeftOpcode, value, | 1087 shiftLower = graph()->NewNode(m->Word64Shl(), value, |
| 1069 jsgraph()->Int64Constant(shiftCount)); | 1088 jsgraph()->Int64Constant(shiftCount)); |
| 1070 shiftHigher = graph()->NewNode(shiftRightOpcode, value, | 1089 shiftHigher = graph()->NewNode(m->Word64Shr(), value, |
| 1071 jsgraph()->Int64Constant(shiftCount)); | 1090 jsgraph()->Int64Constant(shiftCount)); |
| 1072 lowerByte = graph()->NewNode( | 1091 lowerByte = graph()->NewNode( |
| 1073 andOpcode, shiftLower, | 1092 m->Word64And(), shiftLower, |
| 1074 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) | 1093 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) |
| 1075 << (valueSizeInBits - 8 - i))); | 1094 << (valueSizeInBits - 8 - i))); |
| 1076 higherByte = graph()->NewNode( | 1095 higherByte = graph()->NewNode( |
| 1077 andOpcode, shiftHigher, | 1096 m->Word64And(), shiftHigher, |
| 1078 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i)); | 1097 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i)); |
| 1079 } else { | 1098 result = graph()->NewNode(m->Word64Or(), result, lowerByte); |
| 1080 shiftLower = graph()->NewNode(shiftLeftOpcode, value, | 1099 result = graph()->NewNode(m->Word64Or(), result, higherByte); |
| 1081 jsgraph()->Int32Constant(shiftCount)); | 1100 } else { |
| 1082 shiftHigher = graph()->NewNode(shiftRightOpcode, value, | 1101 shiftLower = graph()->NewNode(m->Word32Shl(), value, |
| 1083 jsgraph()->Int32Constant(shiftCount)); | 1102 jsgraph()->Int32Constant(shiftCount)); |
| 1084 lowerByte = graph()->NewNode( | 1103 shiftHigher = graph()->NewNode(m->Word32Shr(), value, |
| 1085 andOpcode, shiftLower, | 1104 jsgraph()->Int32Constant(shiftCount)); |
| 1086 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) | 1105 lowerByte = graph()->NewNode( |
| 1087 << (valueSizeInBits - 8 - i))); | 1106 m->Word32And(), shiftLower, |
| 1088 higherByte = graph()->NewNode( | 1107 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) |
| 1089 andOpcode, shiftHigher, | 1108 << (valueSizeInBits - 8 - i))); |
| 1090 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i)); | 1109 higherByte = graph()->NewNode( |
| 1110 m->Word32And(), shiftHigher, |
| 1111 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i)); |
| 1112 result = graph()->NewNode(m->Word32Or(), result, lowerByte); |
| 1113 result = graph()->NewNode(m->Word32Or(), result, higherByte); |
| 1114 } |
| 1091 } | 1115 } |
| 1092 | |
| 1093 result = graph()->NewNode(orOpcode, result, lowerByte); | |
| 1094 result = graph()->NewNode(orOpcode, result, higherByte); | |
| 1095 } | 1116 } |
| 1096 | 1117 |
| 1097 if (isFloat) { | 1118 if (isFloat) { |
| 1098 switch (memtype.representation()) { | 1119 switch (memtype.representation()) { |
| 1099 case MachineRepresentation::kFloat64: | 1120 case MachineRepresentation::kFloat64: |
| 1100 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result); | 1121 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result); |
| 1101 break; | 1122 break; |
| 1102 case MachineRepresentation::kFloat32: | 1123 case MachineRepresentation::kFloat32: |
| 1103 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result); | 1124 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result); |
| 1104 break; | 1125 break; |
| 1105 default: | 1126 default: |
| 1106 UNREACHABLE(); | 1127 UNREACHABLE(); |
| 1107 break; | 1128 break; |
| 1108 } | 1129 } |
| 1109 } | 1130 } |
| 1110 | 1131 |
| 1111 // We need to sign extend the value | 1132 // We need to sign extend the value |
| 1112 if (memtype.IsSigned()) { | 1133 if (memtype.IsSigned()) { |
| 1113 DCHECK(!isFloat); | 1134 DCHECK(!isFloat); |
| 1114 if (valueSizeInBits < 32) { | 1135 if (valueSizeInBits < 32) { |
| 1115 Node* shiftBitCount; | 1136 Node* shiftBitCount; |
| 1116 // Perform sign extension using following trick | 1137 // Perform sign extension using following trick |
| 1117 // result = (x << machine_width - type_width) >> (machine_width - | 1138 // result = (x << machine_width - type_width) >> (machine_width - |
| 1118 // type_width) | 1139 // type_width) |
| 1119 if (wasmtype == wasm::kAstI64) { | 1140 if (wasmtype == wasm::kAstI64) { |
| 1120 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits); | 1141 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits); |
| 1121 result = graph()->NewNode( | 1142 result = graph()->NewNode( |
| 1122 m->Word64Sar(), | 1143 m->Word64Sar(), |
| 1123 graph()->NewNode(m->Word64Shl(), result, shiftBitCount), | 1144 graph()->NewNode(m->Word64Shl(), |
| 1145 graph()->NewNode(m->ChangeInt32ToInt64(), result), |
| 1146 shiftBitCount), |
| 1124 shiftBitCount); | 1147 shiftBitCount); |
| 1125 } else if (wasmtype == wasm::kAstI32) { | 1148 } else if (wasmtype == wasm::kAstI32) { |
| 1126 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits); | 1149 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits); |
| 1127 result = graph()->NewNode( | 1150 result = graph()->NewNode( |
| 1128 m->Word32Sar(), | 1151 m->Word32Sar(), |
| 1129 graph()->NewNode(m->Word32Shl(), result, shiftBitCount), | 1152 graph()->NewNode(m->Word32Shl(), result, shiftBitCount), |
| 1130 shiftBitCount); | 1153 shiftBitCount); |
| 1131 } | 1154 } |
| 1132 } | 1155 } |
| 1133 } | 1156 } |
| (...skipping 1842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2976 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), | 2999 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |
| 2977 MemBuffer(offset), index, *effect_, *control_); | 3000 MemBuffer(offset), index, *effect_, *control_); |
| 2978 } else { | 3001 } else { |
| 2979 load = graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype), | 3002 load = graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype), |
| 2980 MemBuffer(offset), index, *effect_, *control_); | 3003 MemBuffer(offset), index, *effect_, *control_); |
| 2981 } | 3004 } |
| 2982 | 3005 |
| 2983 *effect_ = load; | 3006 *effect_ = load; |
| 2984 | 3007 |
| 2985 #if defined(V8_TARGET_BIG_ENDIAN) | 3008 #if defined(V8_TARGET_BIG_ENDIAN) |
| 2986 // TODO(john.yan) Implement byte swap turbofan operator | |
| 2987 // and use it if available for better performance | |
| 2988 load = BuildChangeEndianness(load, memtype, type); | 3009 load = BuildChangeEndianness(load, memtype, type); |
| 2989 #endif | 3010 #endif |
| 2990 | 3011 |
| 2991 if (type == wasm::kAstI64 && | 3012 if (type == wasm::kAstI64 && |
| 2992 ElementSizeLog2Of(memtype.representation()) < 3) { | 3013 ElementSizeLog2Of(memtype.representation()) < 3) { |
| 2993 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. | 3014 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. |
| 2994 if (memtype.IsSigned()) { | 3015 if (memtype.IsSigned()) { |
| 2995 // sign extend | 3016 // sign extend |
| 2996 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); | 3017 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); |
| 2997 } else { | 3018 } else { |
| 2998 // zero extend | 3019 // zero extend |
| 2999 load = | 3020 load = |
| 3000 graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load); | 3021 graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load); |
| 3001 } | 3022 } |
| 3002 } | 3023 } |
| 3003 | 3024 |
| 3004 return load; | 3025 return load; |
| 3005 } | 3026 } |
| 3006 | 3027 |
| 3007 | 3028 |
| 3008 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, | 3029 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |
| 3009 uint32_t offset, uint32_t alignment, Node* val, | 3030 uint32_t offset, uint32_t alignment, Node* val, |
| 3010 wasm::WasmCodePosition position) { | 3031 wasm::WasmCodePosition position) { |
| 3011 Node* store; | 3032 Node* store; |
| 3012 | 3033 |
| 3013 // WASM semantics throw on OOB. Introduce explicit bounds check. | 3034 // WASM semantics throw on OOB. Introduce explicit bounds check. |
| 3014 BoundsCheckMem(memtype, index, offset, position); | 3035 BoundsCheckMem(memtype, index, offset, position); |
| 3015 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 3036 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
| 3037 |
| 3016 bool aligned = static_cast<int>(alignment) >= | 3038 bool aligned = static_cast<int>(alignment) >= |
| 3017 ElementSizeLog2Of(memtype.representation()); | 3039 ElementSizeLog2Of(memtype.representation()); |
| 3018 | 3040 |
| 3019 #if defined(V8_TARGET_BIG_ENDIAN) | 3041 #if defined(V8_TARGET_BIG_ENDIAN) |
| 3020 // TODO(john.yan) Implement byte swap turbofan operator | |
| 3021 // and use it if available for better performance | |
| 3022 val = BuildChangeEndianness(val, memtype); | 3042 val = BuildChangeEndianness(val, memtype); |
| 3023 #endif | 3043 #endif |
| 3024 | 3044 |
| 3025 if (aligned || | 3045 if (aligned || |
| 3026 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { | 3046 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { |
| 3027 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 3047 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
| 3028 store = | 3048 store = |
| 3029 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), | 3049 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), |
| 3030 index, val, *effect_, *control_); | 3050 index, val, *effect_, *control_); |
| 3031 } else { | 3051 } else { |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3476 function_->code_start_offset), | 3496 function_->code_start_offset), |
| 3477 compile_ms); | 3497 compile_ms); |
| 3478 } | 3498 } |
| 3479 | 3499 |
| 3480 return code; | 3500 return code; |
| 3481 } | 3501 } |
| 3482 | 3502 |
| 3483 } // namespace compiler | 3503 } // namespace compiler |
| 3484 } // namespace internal | 3504 } // namespace internal |
| 3485 } // namespace v8 | 3505 } // namespace v8 |
| OLD | NEW |