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 988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
999 int64_t masked = (match.Value() & kMask64); | 999 int64_t masked = (match.Value() & kMask64); |
1000 if (match.Value() != masked) node = jsgraph()->Int64Constant(masked); | 1000 if (match.Value() != masked) node = jsgraph()->Int64Constant(masked); |
1001 } else { | 1001 } else { |
1002 node = graph()->NewNode(jsgraph()->machine()->Word64And(), node, | 1002 node = graph()->NewNode(jsgraph()->machine()->Word64And(), node, |
1003 jsgraph()->Int64Constant(kMask64)); | 1003 jsgraph()->Int64Constant(kMask64)); |
1004 } | 1004 } |
1005 } | 1005 } |
1006 return node; | 1006 return node; |
1007 } | 1007 } |
1008 | 1008 |
1009 static bool ReverseBytesSupported(MachineOperatorBuilder* m, | |
1010 size_t size_in_bytes) { | |
1011 switch (size_in_bytes) { | |
1012 case 4: | |
1013 return m->Word32ReverseBytes().IsSupported(); | |
1014 case 8: | |
1015 return m->Word64ReverseBytes().IsSupported(); | |
1016 default: | |
1017 break; | |
1018 } | |
1019 return false; | |
1020 } | |
1021 | |
1009 Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype, | 1022 Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype, |
1010 wasm::LocalType wasmtype) { | 1023 wasm::LocalType wasmtype) { |
1011 Node* result; | 1024 Node* result; |
1012 Node* value = node; | 1025 Node* value = node; |
1013 const Operator* shiftLeftOpcode; | 1026 const Operator* shiftLeftOpcode; |
1014 const Operator* shiftRightOpcode; | 1027 const Operator* shiftRightOpcode; |
1015 const Operator* andOpcode; | 1028 const Operator* andOpcode; |
1016 const Operator* orOpcode; | 1029 const Operator* orOpcode; |
1017 MachineOperatorBuilder* m = jsgraph()->machine(); | 1030 MachineOperatorBuilder* m = jsgraph()->machine(); |
1018 int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation()); | 1031 int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation()); |
1019 int valueSizeInBits = 8 * valueSizeInBytes; | 1032 int valueSizeInBits = 8 * valueSizeInBytes; |
1020 bool isFloat = false; | 1033 bool isFloat = false; |
1021 | 1034 |
1022 switch (memtype.representation()) { | 1035 switch (memtype.representation()) { |
ahaas
2016/07/29 04:15:18
it seems to me that pre-calculating shiftLeftOpcod
john.yan
2016/07/29 17:12:03
xxxOpcode is now removed.
| |
1023 case MachineRepresentation::kFloat64: | 1036 case MachineRepresentation::kFloat64: |
1024 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node); | 1037 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node); |
1025 isFloat = true; | 1038 isFloat = true; |
1026 case MachineRepresentation::kWord64: | 1039 case MachineRepresentation::kWord64: |
1027 shiftLeftOpcode = m->Word64Shl(); | 1040 shiftLeftOpcode = m->Word64Shl(); |
1028 shiftRightOpcode = m->Word64Shr(); | 1041 shiftRightOpcode = m->Word64Shr(); |
1029 andOpcode = m->Word64And(); | 1042 andOpcode = m->Word64And(); |
1030 orOpcode = m->Word64Or(); | 1043 orOpcode = m->Word64Or(); |
1031 result = jsgraph()->Int64Constant(0); | 1044 result = jsgraph()->Int64Constant(0); |
1032 break; | 1045 break; |
(...skipping 13 matching lines...) Expand all Loading... | |
1046 return node; | 1059 return node; |
1047 break; | 1060 break; |
1048 default: | 1061 default: |
1049 UNREACHABLE(); | 1062 UNREACHABLE(); |
1050 break; | 1063 break; |
1051 } | 1064 } |
1052 | 1065 |
1053 int i; | 1066 int i; |
1054 uint32_t shiftCount; | 1067 uint32_t shiftCount; |
1055 | 1068 |
1056 for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2; | 1069 if (ReverseBytesSupported(m, valueSizeInBytes < 4 ? 4 : valueSizeInBytes)) { |
1057 i += 8, shiftCount -= 16) { | 1070 switch (valueSizeInBytes) { |
1058 Node* shiftLower; | 1071 case 1: |
ahaas
2016/07/29 04:15:18
nit: you could remove this case, it should be unre
john.yan
2016/07/29 17:12:03
Done.
| |
1059 Node* shiftHigher; | 1072 break; |
1060 Node* lowerByte; | 1073 case 2: |
1061 Node* higherByte; | 1074 result = |
1075 graph()->NewNode(m->Word32ReverseBytes().op(), | |
1076 graph()->NewNode(shiftLeftOpcode, value, | |
1077 jsgraph()->Int32Constant(16))); | |
1078 break; | |
1079 case 4: | |
1080 result = graph()->NewNode(m->Word32ReverseBytes().op(), value); | |
1081 break; | |
1082 case 8: | |
1083 result = graph()->NewNode(m->Word64ReverseBytes().op(), value); | |
1084 break; | |
1085 default: | |
1086 UNREACHABLE(); | |
1087 } | |
1088 } else { | |
1089 for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2; | |
1090 i += 8, shiftCount -= 16) { | |
1091 Node* shiftLower; | |
1092 Node* shiftHigher; | |
1093 Node* lowerByte; | |
1094 Node* higherByte; | |
1062 | 1095 |
1063 DCHECK(shiftCount > 0); | 1096 DCHECK(shiftCount > 0); |
1064 DCHECK((shiftCount + 8) % 16 == 0); | 1097 DCHECK((shiftCount + 8) % 16 == 0); |
1065 | 1098 |
1066 if (valueSizeInBits > 32) { | 1099 if (valueSizeInBits > 32) { |
1067 shiftLower = graph()->NewNode(shiftLeftOpcode, value, | 1100 shiftLower = graph()->NewNode(shiftLeftOpcode, value, |
1068 jsgraph()->Int64Constant(shiftCount)); | 1101 jsgraph()->Int64Constant(shiftCount)); |
1069 shiftHigher = graph()->NewNode(shiftRightOpcode, value, | 1102 shiftHigher = graph()->NewNode(shiftRightOpcode, value, |
1070 jsgraph()->Int64Constant(shiftCount)); | 1103 jsgraph()->Int64Constant(shiftCount)); |
1071 lowerByte = graph()->NewNode( | 1104 lowerByte = graph()->NewNode( |
1072 andOpcode, shiftLower, | 1105 andOpcode, shiftLower, |
1073 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) | 1106 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) |
1074 << (valueSizeInBits - 8 - i))); | 1107 << (valueSizeInBits - 8 - i))); |
1075 higherByte = graph()->NewNode( | 1108 higherByte = graph()->NewNode( |
1076 andOpcode, shiftHigher, | 1109 andOpcode, shiftHigher, |
1077 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i)); | 1110 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i)); |
1078 } else { | 1111 } else { |
1079 shiftLower = graph()->NewNode(shiftLeftOpcode, value, | 1112 shiftLower = graph()->NewNode(shiftLeftOpcode, value, |
1080 jsgraph()->Int32Constant(shiftCount)); | 1113 jsgraph()->Int32Constant(shiftCount)); |
1081 shiftHigher = graph()->NewNode(shiftRightOpcode, value, | 1114 shiftHigher = graph()->NewNode(shiftRightOpcode, value, |
1082 jsgraph()->Int32Constant(shiftCount)); | 1115 jsgraph()->Int32Constant(shiftCount)); |
1083 lowerByte = graph()->NewNode( | 1116 lowerByte = graph()->NewNode( |
1084 andOpcode, shiftLower, | 1117 andOpcode, shiftLower, |
1085 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) | 1118 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) |
1086 << (valueSizeInBits - 8 - i))); | 1119 << (valueSizeInBits - 8 - i))); |
1087 higherByte = graph()->NewNode( | 1120 higherByte = graph()->NewNode( |
1088 andOpcode, shiftHigher, | 1121 andOpcode, shiftHigher, |
1089 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i)); | 1122 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i)); |
1123 } | |
1124 | |
1125 result = graph()->NewNode(orOpcode, result, lowerByte); | |
1126 result = graph()->NewNode(orOpcode, result, higherByte); | |
1090 } | 1127 } |
1091 | |
1092 result = graph()->NewNode(orOpcode, result, lowerByte); | |
1093 result = graph()->NewNode(orOpcode, result, higherByte); | |
1094 } | 1128 } |
1095 | 1129 |
1096 if (isFloat) { | 1130 if (isFloat) { |
1097 switch (memtype.representation()) { | 1131 switch (memtype.representation()) { |
1098 case MachineRepresentation::kFloat64: | 1132 case MachineRepresentation::kFloat64: |
1099 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result); | 1133 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result); |
1100 break; | 1134 break; |
1101 case MachineRepresentation::kFloat32: | 1135 case MachineRepresentation::kFloat32: |
1102 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result); | 1136 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result); |
1103 break; | 1137 break; |
1104 default: | 1138 default: |
1105 UNREACHABLE(); | 1139 UNREACHABLE(); |
1106 break; | 1140 break; |
1107 } | 1141 } |
1108 } | 1142 } |
1109 | 1143 |
1110 // We need to sign extend the value | 1144 // We need to sign extend the value |
1111 if (memtype.IsSigned()) { | 1145 if (memtype.IsSigned()) { |
1112 DCHECK(!isFloat); | 1146 DCHECK(!isFloat); |
1113 if (valueSizeInBits < 32) { | 1147 if (valueSizeInBits < 32) { |
1114 Node* shiftBitCount; | 1148 Node* shiftBitCount; |
1115 // Perform sign extension using following trick | 1149 // Perform sign extension using following trick |
1116 // result = (x << machine_width - type_width) >> (machine_width - | 1150 // result = (x << machine_width - type_width) >> (machine_width - |
1117 // type_width) | 1151 // type_width) |
1118 if (wasmtype == wasm::kAstI64) { | 1152 if (wasmtype == wasm::kAstI64) { |
1119 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits); | 1153 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits); |
1120 result = graph()->NewNode( | 1154 result = graph()->NewNode( |
1121 m->Word64Sar(), | 1155 m->Word64Sar(), |
1122 graph()->NewNode(m->Word64Shl(), result, shiftBitCount), | 1156 graph()->NewNode(m->Word64Shl(), |
1157 graph()->NewNode(m->ChangeInt32ToInt64(), result), | |
1158 shiftBitCount), | |
1123 shiftBitCount); | 1159 shiftBitCount); |
1124 } else if (wasmtype == wasm::kAstI32) { | 1160 } else if (wasmtype == wasm::kAstI32) { |
1125 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits); | 1161 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits); |
1126 result = graph()->NewNode( | 1162 result = graph()->NewNode( |
1127 m->Word32Sar(), | 1163 m->Word32Sar(), |
1128 graph()->NewNode(m->Word32Shl(), result, shiftBitCount), | 1164 graph()->NewNode(m->Word32Shl(), result, shiftBitCount), |
1129 shiftBitCount); | 1165 shiftBitCount); |
1130 } | 1166 } |
1131 } | 1167 } |
1132 } | 1168 } |
(...skipping 1942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3075 | 3111 |
3076 if (aligned || | 3112 if (aligned || |
3077 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { | 3113 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { |
3078 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), | 3114 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |
3079 MemBuffer(offset), index, *effect_, *control_); | 3115 MemBuffer(offset), index, *effect_, *control_); |
3080 *effect_ = load; | 3116 *effect_ = load; |
3081 } else { | 3117 } else { |
3082 load = BuildUnalignedLoad(type, memtype, index, offset, alignment); | 3118 load = BuildUnalignedLoad(type, memtype, index, offset, alignment); |
3083 } | 3119 } |
3084 #if defined(V8_TARGET_BIG_ENDIAN) | 3120 #if defined(V8_TARGET_BIG_ENDIAN) |
3085 // TODO(john.yan) Implement byte swap turbofan operator | |
3086 // and use it if available for better performance | |
3087 load = BuildChangeEndianness(load, memtype, type); | 3121 load = BuildChangeEndianness(load, memtype, type); |
3088 #endif | 3122 #endif |
3089 | 3123 |
3090 if (type == wasm::kAstI64 && | 3124 if (type == wasm::kAstI64 && |
3091 ElementSizeLog2Of(memtype.representation()) < 3) { | 3125 ElementSizeLog2Of(memtype.representation()) < 3) { |
3092 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. | 3126 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. |
3093 if (memtype.IsSigned()) { | 3127 if (memtype.IsSigned()) { |
3094 // sign extend | 3128 // sign extend |
3095 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); | 3129 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); |
3096 } else { | 3130 } else { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3196 } | 3230 } |
3197 | 3231 |
3198 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, | 3232 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |
3199 uint32_t offset, uint32_t alignment, Node* val, | 3233 uint32_t offset, uint32_t alignment, Node* val, |
3200 wasm::WasmCodePosition position) { | 3234 wasm::WasmCodePosition position) { |
3201 Node* store; | 3235 Node* store; |
3202 | 3236 |
3203 // WASM semantics throw on OOB. Introduce explicit bounds check. | 3237 // WASM semantics throw on OOB. Introduce explicit bounds check. |
3204 BoundsCheckMem(memtype, index, offset, position); | 3238 BoundsCheckMem(memtype, index, offset, position); |
3205 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 3239 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
3240 | |
3206 bool aligned = static_cast<int>(alignment) >= | 3241 bool aligned = static_cast<int>(alignment) >= |
3207 ElementSizeLog2Of(memtype.representation()); | 3242 ElementSizeLog2Of(memtype.representation()); |
3208 | 3243 |
3209 #if defined(V8_TARGET_BIG_ENDIAN) | 3244 #if defined(V8_TARGET_BIG_ENDIAN) |
3210 // TODO(john.yan) Implement byte swap turbofan operator | |
3211 // and use it if available for better performance | |
3212 val = BuildChangeEndianness(val, memtype); | 3245 val = BuildChangeEndianness(val, memtype); |
3213 #endif | 3246 #endif |
3214 | 3247 |
3215 if (aligned || | 3248 if (aligned || |
3216 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { | 3249 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { |
3217 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 3250 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
3218 store = | 3251 store = |
3219 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), | 3252 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), |
3220 index, val, *effect_, *control_); | 3253 index, val, *effect_, *control_); |
3221 *effect_ = store; | 3254 *effect_ = store; |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3661 function_->code_start_offset), | 3694 function_->code_start_offset), |
3662 compile_ms); | 3695 compile_ms); |
3663 } | 3696 } |
3664 | 3697 |
3665 return code; | 3698 return code; |
3666 } | 3699 } |
3667 | 3700 |
3668 } // namespace compiler | 3701 } // namespace compiler |
3669 } // namespace internal | 3702 } // namespace internal |
3670 } // namespace v8 | 3703 } // namespace v8 |
OLD | NEW |