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 |