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 1035 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1046 return node; | 1046 return node; |
1047 break; | 1047 break; |
1048 default: | 1048 default: |
1049 UNREACHABLE(); | 1049 UNREACHABLE(); |
1050 break; | 1050 break; |
1051 } | 1051 } |
1052 | 1052 |
1053 int i; | 1053 int i; |
1054 uint32_t shiftCount; | 1054 uint32_t shiftCount; |
1055 | 1055 |
1056 for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2; | 1056 if (jsgraph()->machine()->ReverseBytesSupported(memtype)) { |
1057 i += 8, shiftCount -= 16) { | 1057 switch (valueSizeInBytes) { |
1058 Node* shiftLower; | 1058 case 1: |
1059 Node* shiftHigher; | 1059 break; |
1060 Node* lowerByte; | 1060 case 2: |
1061 Node* higherByte; | 1061 result = graph()->NewNode( |
| 1062 jsgraph()->machine()->Word16ReverseBytes().op(), value); |
| 1063 break; |
| 1064 case 4: |
| 1065 result = graph()->NewNode( |
| 1066 jsgraph()->machine()->Word32ReverseBytes().op(), value); |
| 1067 break; |
| 1068 case 8: |
| 1069 result = graph()->NewNode( |
| 1070 jsgraph()->machine()->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; |
1062 | 1082 |
1063 DCHECK(shiftCount > 0); | 1083 DCHECK(shiftCount > 0); |
1064 DCHECK((shiftCount + 8) % 16 == 0); | 1084 DCHECK((shiftCount + 8) % 16 == 0); |
1065 | 1085 |
1066 if (valueSizeInBits > 32) { | 1086 if (valueSizeInBits > 32) { |
1067 shiftLower = graph()->NewNode(shiftLeftOpcode, value, | 1087 shiftLower = graph()->NewNode(shiftLeftOpcode, value, |
1068 jsgraph()->Int64Constant(shiftCount)); | 1088 jsgraph()->Int64Constant(shiftCount)); |
1069 shiftHigher = graph()->NewNode(shiftRightOpcode, value, | 1089 shiftHigher = graph()->NewNode(shiftRightOpcode, value, |
1070 jsgraph()->Int64Constant(shiftCount)); | 1090 jsgraph()->Int64Constant(shiftCount)); |
1071 lowerByte = graph()->NewNode( | 1091 lowerByte = graph()->NewNode( |
1072 andOpcode, shiftLower, | 1092 andOpcode, shiftLower, |
1073 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) | 1093 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) |
1074 << (valueSizeInBits - 8 - i))); | 1094 << (valueSizeInBits - 8 - i))); |
1075 higherByte = graph()->NewNode( | 1095 higherByte = graph()->NewNode( |
1076 andOpcode, shiftHigher, | 1096 andOpcode, shiftHigher, |
1077 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i)); | 1097 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i)); |
1078 } else { | 1098 } else { |
1079 shiftLower = graph()->NewNode(shiftLeftOpcode, value, | 1099 shiftLower = graph()->NewNode(shiftLeftOpcode, value, |
1080 jsgraph()->Int32Constant(shiftCount)); | 1100 jsgraph()->Int32Constant(shiftCount)); |
1081 shiftHigher = graph()->NewNode(shiftRightOpcode, value, | 1101 shiftHigher = graph()->NewNode(shiftRightOpcode, value, |
1082 jsgraph()->Int32Constant(shiftCount)); | 1102 jsgraph()->Int32Constant(shiftCount)); |
1083 lowerByte = graph()->NewNode( | 1103 lowerByte = graph()->NewNode( |
1084 andOpcode, shiftLower, | 1104 andOpcode, shiftLower, |
1085 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) | 1105 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) |
1086 << (valueSizeInBits - 8 - i))); | 1106 << (valueSizeInBits - 8 - i))); |
1087 higherByte = graph()->NewNode( | 1107 higherByte = graph()->NewNode( |
1088 andOpcode, shiftHigher, | 1108 andOpcode, shiftHigher, |
1089 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i)); | 1109 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i)); |
| 1110 } |
| 1111 |
| 1112 result = graph()->NewNode(orOpcode, result, lowerByte); |
| 1113 result = graph()->NewNode(orOpcode, result, higherByte); |
1090 } | 1114 } |
1091 | |
1092 result = graph()->NewNode(orOpcode, result, lowerByte); | |
1093 result = graph()->NewNode(orOpcode, result, higherByte); | |
1094 } | 1115 } |
1095 | 1116 |
1096 if (isFloat) { | 1117 if (isFloat) { |
1097 switch (memtype.representation()) { | 1118 switch (memtype.representation()) { |
1098 case MachineRepresentation::kFloat64: | 1119 case MachineRepresentation::kFloat64: |
1099 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result); | 1120 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result); |
1100 break; | 1121 break; |
1101 case MachineRepresentation::kFloat32: | 1122 case MachineRepresentation::kFloat32: |
1102 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result); | 1123 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result); |
1103 break; | 1124 break; |
1104 default: | 1125 default: |
1105 UNREACHABLE(); | 1126 UNREACHABLE(); |
1106 break; | 1127 break; |
1107 } | 1128 } |
1108 } | 1129 } |
1109 | 1130 |
1110 // We need to sign extend the value | 1131 // We need to sign extend the value |
1111 if (memtype.IsSigned()) { | 1132 if (memtype.IsSigned()) { |
1112 DCHECK(!isFloat); | 1133 DCHECK(!isFloat); |
1113 if (valueSizeInBits < 32) { | 1134 if (valueSizeInBits < 32) { |
1114 Node* shiftBitCount; | 1135 Node* shiftBitCount; |
1115 // Perform sign extension using following trick | 1136 // Perform sign extension using following trick |
1116 // result = (x << machine_width - type_width) >> (machine_width - | 1137 // result = (x << machine_width - type_width) >> (machine_width - |
1117 // type_width) | 1138 // type_width) |
1118 if (wasmtype == wasm::kAstI64) { | 1139 if (wasmtype == wasm::kAstI64) { |
1119 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits); | 1140 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits); |
1120 result = graph()->NewNode( | 1141 result = graph()->NewNode( |
1121 m->Word64Sar(), | 1142 m->Word64Sar(), |
1122 graph()->NewNode(m->Word64Shl(), result, shiftBitCount), | 1143 graph()->NewNode( |
| 1144 m->Word64Shl(), |
| 1145 graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), |
| 1146 result), |
| 1147 shiftBitCount), |
1123 shiftBitCount); | 1148 shiftBitCount); |
1124 } else if (wasmtype == wasm::kAstI32) { | 1149 } else if (wasmtype == wasm::kAstI32) { |
1125 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits); | 1150 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits); |
1126 result = graph()->NewNode( | 1151 result = graph()->NewNode( |
1127 m->Word32Sar(), | 1152 m->Word32Sar(), |
1128 graph()->NewNode(m->Word32Shl(), result, shiftBitCount), | 1153 graph()->NewNode(m->Word32Shl(), result, shiftBitCount), |
1129 shiftBitCount); | 1154 shiftBitCount); |
1130 } | 1155 } |
1131 } | 1156 } |
1132 } | 1157 } |
(...skipping 1942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3075 | 3100 |
3076 if (aligned || | 3101 if (aligned || |
3077 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { | 3102 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { |
3078 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), | 3103 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |
3079 MemBuffer(offset), index, *effect_, *control_); | 3104 MemBuffer(offset), index, *effect_, *control_); |
3080 *effect_ = load; | 3105 *effect_ = load; |
3081 } else { | 3106 } else { |
3082 load = BuildUnalignedLoad(type, memtype, index, offset, alignment); | 3107 load = BuildUnalignedLoad(type, memtype, index, offset, alignment); |
3083 } | 3108 } |
3084 #if defined(V8_TARGET_BIG_ENDIAN) | 3109 #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); | 3110 load = BuildChangeEndianness(load, memtype, type); |
3088 #endif | 3111 #endif |
3089 | 3112 |
3090 if (type == wasm::kAstI64 && | 3113 if (type == wasm::kAstI64 && |
3091 ElementSizeLog2Of(memtype.representation()) < 3) { | 3114 ElementSizeLog2Of(memtype.representation()) < 3) { |
3092 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. | 3115 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. |
3093 if (memtype.IsSigned()) { | 3116 if (memtype.IsSigned()) { |
3094 // sign extend | 3117 // sign extend |
3095 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); | 3118 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); |
3096 } else { | 3119 } else { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3196 } | 3219 } |
3197 | 3220 |
3198 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, | 3221 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |
3199 uint32_t offset, uint32_t alignment, Node* val, | 3222 uint32_t offset, uint32_t alignment, Node* val, |
3200 wasm::WasmCodePosition position) { | 3223 wasm::WasmCodePosition position) { |
3201 Node* store; | 3224 Node* store; |
3202 | 3225 |
3203 // WASM semantics throw on OOB. Introduce explicit bounds check. | 3226 // WASM semantics throw on OOB. Introduce explicit bounds check. |
3204 BoundsCheckMem(memtype, index, offset, position); | 3227 BoundsCheckMem(memtype, index, offset, position); |
3205 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 3228 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
| 3229 |
3206 bool aligned = static_cast<int>(alignment) >= | 3230 bool aligned = static_cast<int>(alignment) >= |
3207 ElementSizeLog2Of(memtype.representation()); | 3231 ElementSizeLog2Of(memtype.representation()); |
3208 | 3232 |
3209 #if defined(V8_TARGET_BIG_ENDIAN) | 3233 #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); | 3234 val = BuildChangeEndianness(val, memtype); |
3213 #endif | 3235 #endif |
3214 | 3236 |
3215 if (aligned || | 3237 if (aligned || |
3216 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { | 3238 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { |
3217 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 3239 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
3218 store = | 3240 store = |
3219 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), | 3241 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), |
3220 index, val, *effect_, *control_); | 3242 index, val, *effect_, *control_); |
3221 *effect_ = store; | 3243 *effect_ = store; |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3661 function_->code_start_offset), | 3683 function_->code_start_offset), |
3662 compile_ms); | 3684 compile_ms); |
3663 } | 3685 } |
3664 | 3686 |
3665 return code; | 3687 return code; |
3666 } | 3688 } |
3667 | 3689 |
3668 } // namespace compiler | 3690 } // namespace compiler |
3669 } // namespace internal | 3691 } // namespace internal |
3670 } // namespace v8 | 3692 } // namespace v8 |
OLD | NEW |