| 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 |