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 |
995 Node* WasmGraphBuilder::BuildF32Neg(Node* input) { | 1114 Node* WasmGraphBuilder::BuildF32Neg(Node* input) { |
996 Node* result = | 1115 Node* result = |
997 Unop(wasm::kExprF32ReinterpretI32, | 1116 Unop(wasm::kExprF32ReinterpretI32, |
998 Binop(wasm::kExprI32Xor, Unop(wasm::kExprI32ReinterpretF32, input), | 1117 Binop(wasm::kExprI32Xor, Unop(wasm::kExprI32ReinterpretF32, input), |
999 jsgraph()->Int32Constant(0x80000000))); | 1118 jsgraph()->Int32Constant(0x80000000))); |
1000 | 1119 |
1001 return result; | 1120 return result; |
1002 } | 1121 } |
1003 | 1122 |
1004 Node* WasmGraphBuilder::BuildF64Neg(Node* input) { | 1123 Node* WasmGraphBuilder::BuildF64Neg(Node* input) { |
(...skipping 1737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2742 ElementSizeLog2Of(memtype.representation()); | 2861 ElementSizeLog2Of(memtype.representation()); |
2743 | 2862 |
2744 if (aligned || | 2863 if (aligned || |
2745 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { | 2864 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { |
2746 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), | 2865 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |
2747 MemBuffer(offset), index, *effect_, *control_); | 2866 MemBuffer(offset), index, *effect_, *control_); |
2748 *effect_ = load; | 2867 *effect_ = load; |
2749 } else { | 2868 } else { |
2750 load = BuildUnalignedLoad(type, memtype, index, offset, alignment); | 2869 load = BuildUnalignedLoad(type, memtype, index, offset, alignment); |
2751 } | 2870 } |
| 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 |
2752 | 2876 |
2753 if (type == wasm::kAstI64 && | 2877 if (type == wasm::kAstI64 && |
2754 ElementSizeLog2Of(memtype.representation()) < 3) { | 2878 ElementSizeLog2Of(memtype.representation()) < 3) { |
2755 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. | 2879 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. |
2756 if (memtype.IsSigned()) { | 2880 if (memtype.IsSigned()) { |
2757 // sign extend | 2881 // sign extend |
2758 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); | 2882 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); |
2759 } else { | 2883 } else { |
2760 // zero extend | 2884 // zero extend |
2761 load = | 2885 load = |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2862 uint32_t offset, uint32_t alignment, Node* val, | 2986 uint32_t offset, uint32_t alignment, Node* val, |
2863 wasm::WasmCodePosition position) { | 2987 wasm::WasmCodePosition position) { |
2864 Node* store; | 2988 Node* store; |
2865 | 2989 |
2866 // WASM semantics throw on OOB. Introduce explicit bounds check. | 2990 // WASM semantics throw on OOB. Introduce explicit bounds check. |
2867 BoundsCheckMem(memtype, index, offset, position); | 2991 BoundsCheckMem(memtype, index, offset, position); |
2868 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 2992 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
2869 bool aligned = static_cast<int>(alignment) >= | 2993 bool aligned = static_cast<int>(alignment) >= |
2870 ElementSizeLog2Of(memtype.representation()); | 2994 ElementSizeLog2Of(memtype.representation()); |
2871 | 2995 |
| 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 |
2872 if (aligned || | 3002 if (aligned || |
2873 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { | 3003 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { |
2874 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 3004 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
2875 store = | 3005 store = |
2876 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), | 3006 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), |
2877 index, val, *effect_, *control_); | 3007 index, val, *effect_, *control_); |
2878 *effect_ = store; | 3008 *effect_ = store; |
2879 } else { | 3009 } else { |
2880 store = BuildUnalignedStore(memtype, index, offset, alignment, val); | 3010 store = BuildUnalignedStore(memtype, index, offset, alignment, val); |
2881 } | 3011 } |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3287 function_->code_start_offset), | 3417 function_->code_start_offset), |
3288 compile_ms); | 3418 compile_ms); |
3289 } | 3419 } |
3290 | 3420 |
3291 return code; | 3421 return code; |
3292 } | 3422 } |
3293 | 3423 |
3294 } // namespace compiler | 3424 } // namespace compiler |
3295 } // namespace internal | 3425 } // namespace internal |
3296 } // namespace v8 | 3426 } // namespace v8 |
OLD | NEW |