Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: src/compiler/wasm-compiler.cc

Issue 2122853002: Implement UnaligedLoad and UnaligedStore turbofan operators. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Nits. Fixes some errors Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/compiler/x64/instruction-selector-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 2929 matching lines...) Expand 10 before | Expand all | Expand 10 after
2940 } 2940 }
2941 } 2941 }
2942 2942
2943 Node* cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThan(), index, 2943 Node* cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThan(), index,
2944 jsgraph()->RelocatableInt32Constant( 2944 jsgraph()->RelocatableInt32Constant(
2945 static_cast<uint32_t>(effective_size), 2945 static_cast<uint32_t>(effective_size),
2946 RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); 2946 RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
2947 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position); 2947 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
2948 } 2948 }
2949 2949
2950 MachineType WasmGraphBuilder::GetTypeForUnalignedAccess(uint32_t alignment,
2951 bool signExtend) {
2952 switch (alignment) {
2953 case 0:
2954 return signExtend ? MachineType::Int8() : MachineType::Uint8();
2955 case 1:
2956 return signExtend ? MachineType::Int16() : MachineType::Uint16();
2957 case 2:
2958 return signExtend ? MachineType::Int32() : MachineType::Uint32();
2959 default:
2960 UNREACHABLE();
2961 return MachineType::None();
2962 }
2963 }
2964
2965 Node* WasmGraphBuilder::GetUnalignedLoadOffsetNode(Node* baseOffset,
2966 int numberOfBytes,
2967 int stride, int current) {
2968 int offset;
2969 wasm::WasmOpcode addOpcode;
2970
2971 #if defined(V8_TARGET_LITTLE_ENDIAN)
2972 offset = numberOfBytes - stride - current;
2973 #elif defined(V8_TARGET_BIG_ENDIAN)
2974 offset = current;
2975 #else
2976 #error Unsupported endianness
2977 #endif
2978
2979 #if WASM_64
2980 addOpcode = wasm::kExprI64Add;
2981 #else
2982 addOpcode = wasm::kExprI32Add;
2983 #endif
2984
2985 if (offset == 0) {
2986 return baseOffset;
2987 } else {
2988 return Binop(addOpcode, baseOffset, jsgraph()->Int32Constant(offset));
2989 }
2990 }
2991
2992 Node* WasmGraphBuilder::BuildUnalignedLoad(wasm::LocalType type,
2993 MachineType memtype, Node* index,
2994 uint32_t offset,
2995 uint32_t alignment) {
2996 Node* result;
2997 Node* load;
2998 bool extendTo64Bit = false;
2999
3000 wasm::WasmOpcode shiftOpcode;
3001 wasm::WasmOpcode orOpcode;
3002 Node* shiftConst;
3003
3004 bool signExtend = memtype.IsSigned();
3005
3006 bool isFloat = IsFloatingPoint(memtype.representation());
3007 int stride =
3008 1 << ElementSizeLog2Of(
3009 GetTypeForUnalignedAccess(alignment, false).representation());
3010 int numberOfBytes = 1 << ElementSizeLog2Of(memtype.representation());
3011 DCHECK(numberOfBytes % stride == 0);
3012
3013 switch (type) {
3014 case wasm::kAstI64:
3015 case wasm::kAstF64:
3016 shiftOpcode = wasm::kExprI64Shl;
3017 orOpcode = wasm::kExprI64Ior;
3018 result = jsgraph()->Int64Constant(0);
3019 shiftConst = jsgraph()->Int64Constant(8 * stride);
3020 extendTo64Bit = true;
3021 break;
3022 case wasm::kAstI32:
3023 case wasm::kAstF32:
3024 shiftOpcode = wasm::kExprI32Shl;
3025 orOpcode = wasm::kExprI32Ior;
3026 result = jsgraph()->Int32Constant(0);
3027 shiftConst = jsgraph()->Int32Constant(8 * stride);
3028 break;
3029 default:
3030 UNREACHABLE();
3031 }
3032
3033 Node* baseOffset = MemBuffer(offset);
3034
3035 for (int i = 0; i < numberOfBytes; i += stride) {
3036 result = Binop(shiftOpcode, result, shiftConst);
3037 load = graph()->NewNode(
3038 jsgraph()->machine()->Load(
3039 GetTypeForUnalignedAccess(alignment, signExtend)),
3040 GetUnalignedLoadOffsetNode(baseOffset, numberOfBytes, stride, i), index,
3041 *effect_, *control_);
3042 *effect_ = load;
3043 if (extendTo64Bit) {
3044 if (signExtend) {
3045 load =
3046 graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load);
3047 } else {
3048 load = graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(),
3049 load);
3050 }
3051 }
3052 signExtend = false;
3053 result = Binop(orOpcode, result, load);
3054 }
3055
3056 // Convert to float
3057 if (isFloat) {
3058 switch (type) {
3059 case wasm::kAstF32:
3060 result = Unop(wasm::kExprF32ReinterpretI32, result);
3061 break;
3062 case wasm::kAstF64:
3063 result = Unop(wasm::kExprF64ReinterpretI64, result);
3064 break;
3065 default:
3066 UNREACHABLE();
3067 }
3068 }
3069
3070 return result;
3071 }
3072 2950
3073 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, 2951 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype,
3074 Node* index, uint32_t offset, 2952 Node* index, uint32_t offset,
3075 uint32_t alignment, 2953 uint32_t alignment,
3076 wasm::WasmCodePosition position) { 2954 wasm::WasmCodePosition position) {
3077 Node* load; 2955 Node* load;
3078 2956
3079 // WASM semantics throw on OOB. Introduce explicit bounds check. 2957 // WASM semantics throw on OOB. Introduce explicit bounds check.
3080 BoundsCheckMem(memtype, index, offset, position); 2958 BoundsCheckMem(memtype, index, offset, position);
3081 bool aligned = static_cast<int>(alignment) >= 2959 bool aligned = static_cast<int>(alignment) >=
3082 ElementSizeLog2Of(memtype.representation()); 2960 ElementSizeLog2Of(memtype.representation());
3083 2961
3084 if (aligned || 2962 if (aligned ||
3085 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { 2963 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) {
3086 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), 2964 load = graph()->NewNode(jsgraph()->machine()->Load(memtype),
3087 MemBuffer(offset), index, *effect_, *control_); 2965 MemBuffer(offset), index, *effect_, *control_);
3088 *effect_ = load;
3089 } else { 2966 } else {
3090 load = BuildUnalignedLoad(type, memtype, index, offset, alignment); 2967 load = graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype),
2968 MemBuffer(offset), index, *effect_, *control_);
3091 } 2969 }
2970
2971 *effect_ = load;
2972
3092 #if defined(V8_TARGET_BIG_ENDIAN) 2973 #if defined(V8_TARGET_BIG_ENDIAN)
3093 // TODO(john.yan) Implement byte swap turbofan operator 2974 // TODO(john.yan) Implement byte swap turbofan operator
3094 // and use it if available for better performance 2975 // and use it if available for better performance
3095 load = BuildChangeEndianness(load, memtype, type); 2976 load = BuildChangeEndianness(load, memtype, type);
3096 #endif 2977 #endif
3097 2978
3098 if (type == wasm::kAstI64 && 2979 if (type == wasm::kAstI64 &&
3099 ElementSizeLog2Of(memtype.representation()) < 3) { 2980 ElementSizeLog2Of(memtype.representation()) < 3) {
3100 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. 2981 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes.
3101 if (memtype.IsSigned()) { 2982 if (memtype.IsSigned()) {
3102 // sign extend 2983 // sign extend
3103 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); 2984 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load);
3104 } else { 2985 } else {
3105 // zero extend 2986 // zero extend
3106 load = 2987 load =
3107 graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load); 2988 graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load);
3108 } 2989 }
3109 } 2990 }
3110 2991
3111 return load; 2992 return load;
3112 } 2993 }
3113 2994
3114 Node* WasmGraphBuilder::GetUnalignedStoreOffsetNode(Node* baseOffset,
3115 int numberOfBytes,
3116 int stride, int current) {
3117 int offset;
3118 wasm::WasmOpcode addOpcode;
3119
3120 #if defined(V8_TARGET_LITTLE_ENDIAN)
3121 offset = current;
3122 #elif defined(V8_TARGET_BIG_ENDIAN)
3123 offset = numberOfBytes - stride - current;
3124 #else
3125 #error Unsupported endianness
3126 #endif
3127
3128 #if WASM_64
3129 addOpcode = wasm::kExprI64Add;
3130 #else
3131 addOpcode = wasm::kExprI32Add;
3132 #endif
3133
3134 if (offset == 0) {
3135 return baseOffset;
3136 } else {
3137 return Binop(addOpcode, baseOffset, jsgraph()->Int32Constant(offset));
3138 }
3139 }
3140
3141 Node* WasmGraphBuilder::BuildUnalignedStore(MachineType memtype, Node* index,
3142 uint32_t offset, uint32_t alignment,
3143 Node* val) {
3144 Node* store;
3145 Node* newValue;
3146
3147 wasm::WasmOpcode shiftOpcode;
3148
3149 Node* shiftConst;
3150 bool extendTo64Bit = false;
3151 bool isFloat = IsFloatingPoint(memtype.representation());
3152 int stride = 1 << ElementSizeLog2Of(
3153 GetTypeForUnalignedAccess(alignment).representation());
3154 int numberOfBytes = 1 << ElementSizeLog2Of(memtype.representation());
3155 DCHECK(numberOfBytes % stride == 0);
3156
3157 StoreRepresentation rep(GetTypeForUnalignedAccess(alignment).representation(),
3158 kNoWriteBarrier);
3159
3160 if (ElementSizeLog2Of(memtype.representation()) <= 2) {
3161 shiftOpcode = wasm::kExprI32ShrU;
3162 shiftConst = jsgraph()->Int32Constant(8 * stride);
3163 } else {
3164 shiftOpcode = wasm::kExprI64ShrU;
3165 shiftConst = jsgraph()->Int64Constant(8 * stride);
3166 extendTo64Bit = true;
3167 }
3168
3169 newValue = val;
3170 if (isFloat) {
3171 switch (memtype.representation()) {
3172 case MachineRepresentation::kFloat64:
3173 newValue = Unop(wasm::kExprI64ReinterpretF64, val);
3174 break;
3175 case MachineRepresentation::kFloat32:
3176 newValue = Unop(wasm::kExprI32ReinterpretF32, val);
3177 break;
3178 default:
3179 UNREACHABLE();
3180 }
3181 }
3182
3183 Node* baseOffset = MemBuffer(offset);
3184
3185 for (int i = 0; i < numberOfBytes - stride; i += stride) {
3186 store = graph()->NewNode(
3187 jsgraph()->machine()->Store(rep),
3188 GetUnalignedStoreOffsetNode(baseOffset, numberOfBytes, stride, i),
3189 index,
3190 extendTo64Bit ? Unop(wasm::kExprI32ConvertI64, newValue) : newValue,
3191 *effect_, *control_);
3192 newValue = Binop(shiftOpcode, newValue, shiftConst);
3193 *effect_ = store;
3194 }
3195 store = graph()->NewNode(
3196 jsgraph()->machine()->Store(rep),
3197 GetUnalignedStoreOffsetNode(baseOffset, numberOfBytes, stride,
3198 numberOfBytes - stride),
3199 index,
3200 extendTo64Bit ? Unop(wasm::kExprI32ConvertI64, newValue) : newValue,
3201 *effect_, *control_);
3202 *effect_ = store;
3203 return val;
3204 }
3205 2995
3206 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, 2996 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index,
3207 uint32_t offset, uint32_t alignment, Node* val, 2997 uint32_t offset, uint32_t alignment, Node* val,
3208 wasm::WasmCodePosition position) { 2998 wasm::WasmCodePosition position) {
3209 Node* store; 2999 Node* store;
3210 3000
3211 // WASM semantics throw on OOB. Introduce explicit bounds check. 3001 // WASM semantics throw on OOB. Introduce explicit bounds check.
3212 BoundsCheckMem(memtype, index, offset, position); 3002 BoundsCheckMem(memtype, index, offset, position);
3213 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); 3003 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
3214 bool aligned = static_cast<int>(alignment) >= 3004 bool aligned = static_cast<int>(alignment) >=
3215 ElementSizeLog2Of(memtype.representation()); 3005 ElementSizeLog2Of(memtype.representation());
3216 3006
3217 #if defined(V8_TARGET_BIG_ENDIAN) 3007 #if defined(V8_TARGET_BIG_ENDIAN)
3218 // TODO(john.yan) Implement byte swap turbofan operator 3008 // TODO(john.yan) Implement byte swap turbofan operator
3219 // and use it if available for better performance 3009 // and use it if available for better performance
3220 val = BuildChangeEndianness(val, memtype); 3010 val = BuildChangeEndianness(val, memtype);
3221 #endif 3011 #endif
3222 3012
3223 if (aligned || 3013 if (aligned ||
3224 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { 3014 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) {
3225 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); 3015 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
3226 store = 3016 store =
3227 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), 3017 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset),
3228 index, val, *effect_, *control_); 3018 index, val, *effect_, *control_);
3229 *effect_ = store;
3230 } else { 3019 } else {
3231 store = BuildUnalignedStore(memtype, index, offset, alignment, val); 3020 UnalignedStoreRepresentation rep(memtype.representation());
3021 store =
3022 graph()->NewNode(jsgraph()->machine()->UnalignedStore(rep),
3023 MemBuffer(offset), index, val, *effect_, *control_);
3232 } 3024 }
3233 3025
3026 *effect_ = store;
3027
3234 return store; 3028 return store;
3235 } 3029 }
3236 3030
3237 Node* WasmGraphBuilder::BuildAsmjsLoadMem(MachineType type, Node* index) { 3031 Node* WasmGraphBuilder::BuildAsmjsLoadMem(MachineType type, Node* index) {
3238 // TODO(turbofan): fold bounds checks for constant asm.js loads. 3032 // TODO(turbofan): fold bounds checks for constant asm.js loads.
3239 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). 3033 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish).
3240 const Operator* op = jsgraph()->machine()->CheckedLoad(type); 3034 const Operator* op = jsgraph()->machine()->CheckedLoad(type);
3241 Node* load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_, 3035 Node* load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_,
3242 *control_); 3036 *control_);
3243 *effect_ = load; 3037 *effect_ = load;
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
3548 : thrower_(thrower), 3342 : thrower_(thrower),
3549 isolate_(isolate), 3343 isolate_(isolate),
3550 module_env_(module_env), 3344 module_env_(module_env),
3551 function_(function), 3345 function_(function),
3552 graph_zone_(new Zone(isolate->allocator())), 3346 graph_zone_(new Zone(isolate->allocator())),
3553 jsgraph_(new (graph_zone()) JSGraph( 3347 jsgraph_(new (graph_zone()) JSGraph(
3554 isolate, new (graph_zone()) Graph(graph_zone()), 3348 isolate, new (graph_zone()) Graph(graph_zone()),
3555 new (graph_zone()) CommonOperatorBuilder(graph_zone()), nullptr, 3349 new (graph_zone()) CommonOperatorBuilder(graph_zone()), nullptr,
3556 nullptr, new (graph_zone()) MachineOperatorBuilder( 3350 nullptr, new (graph_zone()) MachineOperatorBuilder(
3557 graph_zone(), MachineType::PointerRepresentation(), 3351 graph_zone(), MachineType::PointerRepresentation(),
3558 InstructionSelector::SupportedMachineOperatorFlags()))), 3352 InstructionSelector::SupportedMachineOperatorFlags(),
3353 InstructionSelector::AlignmentRequirements()))),
3559 compilation_zone_(isolate->allocator()), 3354 compilation_zone_(isolate->allocator()),
3560 info_(function->name_length != 0 3355 info_(function->name_length != 0
3561 ? module_env->module->GetNameOrNull(function->name_offset, 3356 ? module_env->module->GetNameOrNull(function->name_offset,
3562 function->name_length) 3357 function->name_length)
3563 : ArrayVector("wasm"), 3358 : ArrayVector("wasm"),
3564 isolate, &compilation_zone_, 3359 isolate, &compilation_zone_,
3565 Code::ComputeFlags(Code::WASM_FUNCTION)), 3360 Code::ComputeFlags(Code::WASM_FUNCTION)),
3566 job_(), 3361 job_(),
3567 index_(index), 3362 index_(index),
3568 ok_(true) { 3363 ok_(true) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
3669 function_->code_start_offset), 3464 function_->code_start_offset),
3670 compile_ms); 3465 compile_ms);
3671 } 3466 }
3672 3467
3673 return code; 3468 return code;
3674 } 3469 }
3675 3470
3676 } // namespace compiler 3471 } // namespace compiler
3677 } // namespace internal 3472 } // namespace internal
3678 } // namespace v8 3473 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/compiler/x64/instruction-selector-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698