| 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 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 int64_t masked = (match.Value() & kMask64); | 985 int64_t masked = (match.Value() & kMask64); |
| 986 if (match.Value() != masked) node = jsgraph()->Int64Constant(masked); | 986 if (match.Value() != masked) node = jsgraph()->Int64Constant(masked); |
| 987 } else { | 987 } else { |
| 988 node = graph()->NewNode(jsgraph()->machine()->Word64And(), node, | 988 node = graph()->NewNode(jsgraph()->machine()->Word64And(), node, |
| 989 jsgraph()->Int64Constant(kMask64)); | 989 jsgraph()->Int64Constant(kMask64)); |
| 990 } | 990 } |
| 991 } | 991 } |
| 992 return node; | 992 return node; |
| 993 } | 993 } |
| 994 | 994 |
| 995 Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype, | |
| 996 wasm::LocalType wasmtype) { | |
| 997 Node* result; | |
| 998 Node* value = node; | |
| 999 const Operator* shiftLeftOpcode; | |
| 1000 const Operator* shiftRightOpcode; | |
| 1001 const Operator* andOpcode; | |
| 1002 const Operator* orOpcode; | |
| 1003 MachineOperatorBuilder* m = jsgraph()->machine(); | |
| 1004 int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation()); | |
| 1005 int valueSizeInBits = 8 * valueSizeInBytes; | |
| 1006 bool isFloat = false; | |
| 1007 | |
| 1008 switch (memtype.representation()) { | |
| 1009 case MachineRepresentation::kFloat64: | |
| 1010 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node); | |
| 1011 isFloat = true; | |
| 1012 case MachineRepresentation::kWord64: | |
| 1013 shiftLeftOpcode = m->Word64Shl(); | |
| 1014 shiftRightOpcode = m->Word64Shr(); | |
| 1015 andOpcode = m->Word64And(); | |
| 1016 orOpcode = m->Word64Or(); | |
| 1017 result = jsgraph()->Int64Constant(0); | |
| 1018 break; | |
| 1019 case MachineRepresentation::kFloat32: | |
| 1020 value = graph()->NewNode(m->BitcastFloat32ToInt32(), node); | |
| 1021 isFloat = true; | |
| 1022 case MachineRepresentation::kWord32: | |
| 1023 case MachineRepresentation::kWord16: | |
| 1024 shiftLeftOpcode = m->Word32Shl(); | |
| 1025 shiftRightOpcode = m->Word32Shr(); | |
| 1026 andOpcode = m->Word32And(); | |
| 1027 orOpcode = m->Word32Or(); | |
| 1028 result = jsgraph()->Int32Constant(0); | |
| 1029 break; | |
| 1030 case MachineRepresentation::kWord8: | |
| 1031 // No need to change endianness for byte size, return original node | |
| 1032 return node; | |
| 1033 break; | |
| 1034 default: | |
| 1035 UNREACHABLE(); | |
| 1036 break; | |
| 1037 } | |
| 1038 | |
| 1039 int i; | |
| 1040 uint32_t shiftCount; | |
| 1041 | |
| 1042 for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2; | |
| 1043 i += 8, shiftCount -= 16) { | |
| 1044 DCHECK(shiftCount > 0); | |
| 1045 DCHECK((shiftCount + 8) % 16 == 0); | |
| 1046 | |
| 1047 Node* shiftLower = graph()->NewNode(shiftLeftOpcode, value, | |
| 1048 jsgraph()->Int32Constant(shiftCount)); | |
| 1049 Node* shiftHigher = graph()->NewNode(shiftRightOpcode, value, | |
| 1050 jsgraph()->Int32Constant(shiftCount)); | |
| 1051 | |
| 1052 Node* lowerByte; | |
| 1053 Node* higherByte; | |
| 1054 | |
| 1055 if (valueSizeInBits > 32) { | |
| 1056 lowerByte = graph()->NewNode( | |
| 1057 andOpcode, shiftLower, | |
| 1058 jsgraph()->Int64Constant(0xFFl << (valueSizeInBits - 8 - i))); | |
| 1059 higherByte = graph()->NewNode(andOpcode, shiftHigher, | |
| 1060 jsgraph()->Int64Constant(0xFFl << i)); | |
| 1061 } else { | |
| 1062 lowerByte = graph()->NewNode( | |
| 1063 andOpcode, shiftLower, | |
| 1064 jsgraph()->Int32Constant(0xFF << (valueSizeInBits - 8 - i))); | |
| 1065 higherByte = graph()->NewNode(andOpcode, shiftHigher, | |
| 1066 jsgraph()->Int32Constant(0xFF << i)); | |
| 1067 } | |
| 1068 | |
| 1069 result = graph()->NewNode(orOpcode, result, lowerByte); | |
| 1070 result = graph()->NewNode(orOpcode, result, higherByte); | |
| 1071 } | |
| 1072 | |
| 1073 if (isFloat) { | |
| 1074 switch (memtype.representation()) { | |
| 1075 case MachineRepresentation::kFloat64: | |
| 1076 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result); | |
| 1077 break; | |
| 1078 case MachineRepresentation::kFloat32: | |
| 1079 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result); | |
| 1080 break; | |
| 1081 default: | |
| 1082 UNREACHABLE(); | |
| 1083 break; | |
| 1084 } | |
| 1085 } | |
| 1086 | |
| 1087 // We need to sign extend the value | |
| 1088 if (memtype.IsSigned()) { | |
| 1089 DCHECK(!isFloat); | |
| 1090 if (valueSizeInBits < 32) { | |
| 1091 Node* shiftBitCount; | |
| 1092 // Perform sign extension using following trick | |
| 1093 // result = (x << machine_width - type_width) >> (machine_width - | |
| 1094 // type_width) | |
| 1095 if (wasmtype == wasm::kAstI64) { | |
| 1096 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits); | |
| 1097 result = graph()->NewNode( | |
| 1098 m->Word64Sar(), | |
| 1099 graph()->NewNode(m->Word64Shl(), result, shiftBitCount), | |
| 1100 shiftBitCount); | |
| 1101 } else if (wasmtype == wasm::kAstI32) { | |
| 1102 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits); | |
| 1103 result = graph()->NewNode( | |
| 1104 m->Word32Sar(), | |
| 1105 graph()->NewNode(m->Word32Shl(), result, shiftBitCount), | |
| 1106 shiftBitCount); | |
| 1107 } | |
| 1108 } | |
| 1109 } | |
| 1110 | |
| 1111 return result; | |
| 1112 } | |
| 1113 | |
| 1114 Node* WasmGraphBuilder::BuildF32Neg(Node* input) { | 995 Node* WasmGraphBuilder::BuildF32Neg(Node* input) { |
| 1115 Node* result = | 996 Node* result = |
| 1116 Unop(wasm::kExprF32ReinterpretI32, | 997 Unop(wasm::kExprF32ReinterpretI32, |
| 1117 Binop(wasm::kExprI32Xor, Unop(wasm::kExprI32ReinterpretF32, input), | 998 Binop(wasm::kExprI32Xor, Unop(wasm::kExprI32ReinterpretF32, input), |
| 1118 jsgraph()->Int32Constant(0x80000000))); | 999 jsgraph()->Int32Constant(0x80000000))); |
| 1119 | 1000 |
| 1120 return result; | 1001 return result; |
| 1121 } | 1002 } |
| 1122 | 1003 |
| 1123 Node* WasmGraphBuilder::BuildF64Neg(Node* input) { | 1004 Node* WasmGraphBuilder::BuildF64Neg(Node* input) { |
| (...skipping 1737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2861 ElementSizeLog2Of(memtype.representation()); | 2742 ElementSizeLog2Of(memtype.representation()); |
| 2862 | 2743 |
| 2863 if (aligned || | 2744 if (aligned || |
| 2864 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { | 2745 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { |
| 2865 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), | 2746 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |
| 2866 MemBuffer(offset), index, *effect_, *control_); | 2747 MemBuffer(offset), index, *effect_, *control_); |
| 2867 *effect_ = load; | 2748 *effect_ = load; |
| 2868 } else { | 2749 } else { |
| 2869 load = BuildUnalignedLoad(type, memtype, index, offset, alignment); | 2750 load = BuildUnalignedLoad(type, memtype, index, offset, alignment); |
| 2870 } | 2751 } |
| 2871 #if defined(V8_TARGET_BIG_ENDIAN) | |
| 2872 // TODO(john.yan) Implement byte swap turbofan operator | |
| 2873 // and use it if available for better performance | |
| 2874 load = BuildChangeEndianness(load, memtype, type); | |
| 2875 #endif | |
| 2876 | 2752 |
| 2877 if (type == wasm::kAstI64 && | 2753 if (type == wasm::kAstI64 && |
| 2878 ElementSizeLog2Of(memtype.representation()) < 3) { | 2754 ElementSizeLog2Of(memtype.representation()) < 3) { |
| 2879 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. | 2755 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. |
| 2880 if (memtype.IsSigned()) { | 2756 if (memtype.IsSigned()) { |
| 2881 // sign extend | 2757 // sign extend |
| 2882 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); | 2758 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); |
| 2883 } else { | 2759 } else { |
| 2884 // zero extend | 2760 // zero extend |
| 2885 load = | 2761 load = |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2986 uint32_t offset, uint32_t alignment, Node* val, | 2862 uint32_t offset, uint32_t alignment, Node* val, |
| 2987 wasm::WasmCodePosition position) { | 2863 wasm::WasmCodePosition position) { |
| 2988 Node* store; | 2864 Node* store; |
| 2989 | 2865 |
| 2990 // WASM semantics throw on OOB. Introduce explicit bounds check. | 2866 // WASM semantics throw on OOB. Introduce explicit bounds check. |
| 2991 BoundsCheckMem(memtype, index, offset, position); | 2867 BoundsCheckMem(memtype, index, offset, position); |
| 2992 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 2868 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
| 2993 bool aligned = static_cast<int>(alignment) >= | 2869 bool aligned = static_cast<int>(alignment) >= |
| 2994 ElementSizeLog2Of(memtype.representation()); | 2870 ElementSizeLog2Of(memtype.representation()); |
| 2995 | 2871 |
| 2996 #if defined(V8_TARGET_BIG_ENDIAN) | |
| 2997 // TODO(john.yan) Implement byte swap turbofan operator | |
| 2998 // and use it if available for better performance | |
| 2999 val = BuildChangeEndianness(val, memtype); | |
| 3000 #endif | |
| 3001 | |
| 3002 if (aligned || | 2872 if (aligned || |
| 3003 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { | 2873 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { |
| 3004 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 2874 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
| 3005 store = | 2875 store = |
| 3006 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), | 2876 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), |
| 3007 index, val, *effect_, *control_); | 2877 index, val, *effect_, *control_); |
| 3008 *effect_ = store; | 2878 *effect_ = store; |
| 3009 } else { | 2879 } else { |
| 3010 store = BuildUnalignedStore(memtype, index, offset, alignment, val); | 2880 store = BuildUnalignedStore(memtype, index, offset, alignment, val); |
| 3011 } | 2881 } |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3417 function_->code_start_offset), | 3287 function_->code_start_offset), |
| 3418 compile_ms); | 3288 compile_ms); |
| 3419 } | 3289 } |
| 3420 | 3290 |
| 3421 return code; | 3291 return code; |
| 3422 } | 3292 } |
| 3423 | 3293 |
| 3424 } // namespace compiler | 3294 } // namespace compiler |
| 3425 } // namespace internal | 3295 } // namespace internal |
| 3426 } // namespace v8 | 3296 } // namespace v8 |
| OLD | NEW |