Chromium Code Reviews| 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 |