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 |