| 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 2573 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2584     size_t limit = size - offset - memsize; |  2584     size_t limit = size - offset - memsize; | 
|  2585     CHECK(limit <= kMaxUInt32); |  2585     CHECK(limit <= kMaxUInt32); | 
|  2586     cond = graph()->NewNode( |  2586     cond = graph()->NewNode( | 
|  2587         jsgraph()->machine()->Uint32LessThanOrEqual(), index, |  2587         jsgraph()->machine()->Uint32LessThanOrEqual(), index, | 
|  2588         jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); |  2588         jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); | 
|  2589   } |  2589   } | 
|  2590  |  2590  | 
|  2591   trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position); |  2591   trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position); | 
|  2592 } |  2592 } | 
|  2593  |  2593  | 
 |  2594 MachineType WasmGraphBuilder::GetTypeForUnalignedAccess(uint32_t alignment, | 
 |  2595                                                         bool signExtend) { | 
 |  2596   switch (alignment) { | 
 |  2597     case 0: | 
 |  2598       return signExtend ? MachineType::Int8() : MachineType::Uint8(); | 
 |  2599     case 1: | 
 |  2600       return signExtend ? MachineType::Int16() : MachineType::Uint16(); | 
 |  2601     case 2: | 
 |  2602       return signExtend ? MachineType::Int32() : MachineType::Uint32(); | 
 |  2603     default: | 
 |  2604       UNREACHABLE(); | 
 |  2605   } | 
 |  2606 } | 
 |  2607  | 
 |  2608 Node* WasmGraphBuilder::GetUnalignedLoadOffsetNode(Node* baseOffset, | 
 |  2609                                                    int numberOfBytes, | 
 |  2610                                                    int stride, int current) { | 
 |  2611   int offset; | 
 |  2612  | 
 |  2613 #if defined(V8_TARGET_LITTLE_ENDIAN) | 
 |  2614   offset = numberOfBytes - stride - current; | 
 |  2615 #elif defined(V8_TARGET_BIG_ENDIAN) | 
 |  2616   offset = current; | 
 |  2617 #else | 
 |  2618 #error Unsupported endianness | 
 |  2619 #endif | 
 |  2620  | 
 |  2621   if (offset == 0) { | 
 |  2622     return baseOffset; | 
 |  2623   } else { | 
 |  2624     return Binop(wasm::kExprI32Add, baseOffset, | 
 |  2625                  jsgraph()->Int32Constant(offset)); | 
 |  2626   } | 
 |  2627 } | 
 |  2628  | 
 |  2629 Node* WasmGraphBuilder::BuildUnalignedLoad(wasm::LocalType type, | 
 |  2630                                            MachineType memtype, Node* index, | 
 |  2631                                            uint32_t offset, | 
 |  2632                                            uint32_t alignment) { | 
 |  2633   Node* result; | 
 |  2634   Node* load; | 
 |  2635   bool extendTo64Bit = false; | 
 |  2636  | 
 |  2637   wasm::WasmOpcode shiftOpcode; | 
 |  2638   wasm::WasmOpcode orOpcode; | 
 |  2639   Node* shiftConst; | 
 |  2640  | 
 |  2641   bool signExtend = memtype.IsSigned(); | 
 |  2642  | 
 |  2643   bool isFloat = IsFloatingPoint(memtype.representation()); | 
 |  2644   int stride = | 
 |  2645       1 << ElementSizeLog2Of( | 
 |  2646           GetTypeForUnalignedAccess(alignment, false).representation()); | 
 |  2647   int numberOfBytes = 1 << ElementSizeLog2Of(memtype.representation()); | 
 |  2648   int numberOfLoads = numberOfBytes / stride; | 
 |  2649  | 
 |  2650   DCHECK(numberOfBytes % stride == 0); | 
 |  2651   DCHECK(numberOfLoads >= 2); | 
 |  2652  | 
 |  2653   switch (type) { | 
 |  2654     case wasm::kAstI64: | 
 |  2655     case wasm::kAstF64: | 
 |  2656       shiftOpcode = wasm::kExprI64Shl; | 
 |  2657       orOpcode = wasm::kExprI64Ior; | 
 |  2658       result = jsgraph()->Int64Constant(0); | 
 |  2659       shiftConst = jsgraph()->Int64Constant(8 * stride); | 
 |  2660       extendTo64Bit = true; | 
 |  2661       break; | 
 |  2662     case wasm::kAstI32: | 
 |  2663     case wasm::kAstF32: | 
 |  2664       shiftOpcode = wasm::kExprI32Shl; | 
 |  2665       orOpcode = wasm::kExprI32Ior; | 
 |  2666       result = jsgraph()->Int32Constant(0); | 
 |  2667       shiftConst = jsgraph()->Int32Constant(8 * stride); | 
 |  2668       break; | 
 |  2669     default: | 
 |  2670       UNREACHABLE(); | 
 |  2671   } | 
 |  2672  | 
 |  2673   Node* baseOffset = MemBuffer(offset); | 
 |  2674  | 
 |  2675   for (int i = 0; i < numberOfBytes; i += stride) { | 
 |  2676     result = Binop(shiftOpcode, result, shiftConst); | 
 |  2677     load = graph()->NewNode( | 
 |  2678         jsgraph()->machine()->Load( | 
 |  2679             GetTypeForUnalignedAccess(alignment, signExtend)), | 
 |  2680         GetUnalignedLoadOffsetNode(baseOffset, numberOfBytes, stride, i), index, | 
 |  2681         *effect_, *control_); | 
 |  2682     *effect_ = load; | 
 |  2683     if (extendTo64Bit) { | 
 |  2684       if (signExtend) { | 
 |  2685         load = | 
 |  2686             graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); | 
 |  2687       } else { | 
 |  2688         load = graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), | 
 |  2689                                 load); | 
 |  2690       } | 
 |  2691     } | 
 |  2692     signExtend = false; | 
 |  2693     result = Binop(orOpcode, result, load); | 
 |  2694   } | 
 |  2695  | 
 |  2696   // Convert to float | 
 |  2697   if (isFloat) { | 
 |  2698     switch (type) { | 
 |  2699       case wasm::kAstF32: | 
 |  2700         result = Unop(wasm::kExprF32ReinterpretI32, result); | 
 |  2701         break; | 
 |  2702       case wasm::kAstF64: | 
 |  2703         result = Unop(wasm::kExprF64ReinterpretI64, result); | 
 |  2704         break; | 
 |  2705       default: | 
 |  2706         UNREACHABLE(); | 
 |  2707     } | 
 |  2708   } | 
 |  2709  | 
 |  2710   return result; | 
 |  2711 } | 
 |  2712  | 
|  2594 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, |  2713 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, | 
|  2595                                 Node* index, uint32_t offset, |  2714                                 Node* index, uint32_t offset, | 
 |  2715                                 uint32_t alignment, | 
|  2596                                 wasm::WasmCodePosition position) { |  2716                                 wasm::WasmCodePosition position) { | 
|  2597   Node* load; |  2717   Node* load; | 
|  2598  |  2718  | 
|  2599   if (module_ && module_->asm_js()) { |  2719   if (module_ && module_->asm_js()) { | 
|  2600     // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). |  2720     // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). | 
|  2601     DCHECK_EQ(0, offset); |  2721     DCHECK_EQ(0, offset); | 
|  2602     const Operator* op = jsgraph()->machine()->CheckedLoad(memtype); |  2722     const Operator* op = jsgraph()->machine()->CheckedLoad(memtype); | 
|  2603     load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_, |  2723     load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_, | 
|  2604                             *control_); |  2724                             *control_); | 
 |  2725     *effect_ = load; | 
|  2605   } else { |  2726   } else { | 
|  2606     // WASM semantics throw on OOB. Introduce explicit bounds check. |  2727     // WASM semantics throw on OOB. Introduce explicit bounds check. | 
|  2607     BoundsCheckMem(memtype, index, offset, position); |  2728     BoundsCheckMem(memtype, index, offset, position); | 
|  2608     load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |  2729     bool aligned = alignment >= ElementSizeLog2Of(memtype.representation()); | 
|  2609                             MemBuffer(offset), index, *effect_, *control_); |  2730  | 
 |  2731     if (aligned || | 
 |  2732         jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { | 
 |  2733       load = graph()->NewNode(jsgraph()->machine()->Load(memtype), | 
 |  2734                               MemBuffer(offset), index, *effect_, *control_); | 
 |  2735       *effect_ = load; | 
 |  2736     } else { | 
 |  2737       load = BuildUnalignedLoad(type, memtype, index, offset, alignment); | 
 |  2738     } | 
|  2610   } |  2739   } | 
|  2611  |  2740  | 
|  2612   *effect_ = load; |  | 
|  2613  |  | 
|  2614   if (type == wasm::kAstI64 && |  2741   if (type == wasm::kAstI64 && | 
|  2615       ElementSizeLog2Of(memtype.representation()) < 3) { |  2742       ElementSizeLog2Of(memtype.representation()) < 3) { | 
|  2616     // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. |  2743     // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. | 
|  2617     if (memtype.IsSigned()) { |  2744     if (memtype.IsSigned()) { | 
|  2618       // sign extend |  2745       // sign extend | 
|  2619       load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); |  2746       load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); | 
|  2620     } else { |  2747     } else { | 
|  2621       // zero extend |  2748       // zero extend | 
|  2622       load = |  2749       load = | 
|  2623           graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load); |  2750           graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load); | 
|  2624     } |  2751     } | 
|  2625   } |  2752   } | 
|  2626  |  2753  | 
|  2627   return load; |  2754   return load; | 
|  2628 } |  2755 } | 
|  2629  |  2756  | 
 |  2757 Node* WasmGraphBuilder::GetUnalignedStoreOffsetNode(Node* baseOffset, | 
 |  2758                                                     int numberOfBytes, | 
 |  2759                                                     int stride, int current) { | 
 |  2760   int offset; | 
 |  2761 #if defined(V8_TARGET_LITTLE_ENDIAN) | 
 |  2762   offset = current; | 
 |  2763 #elif defined(V8_TARGET_BIG_ENDIAN) | 
 |  2764   offset = numberOfBytes - stride - current; | 
 |  2765 #else | 
 |  2766 #error Unsupported endianness | 
 |  2767 #endif | 
 |  2768   if (offset == 0) { | 
 |  2769     return baseOffset; | 
 |  2770   } else { | 
 |  2771     return Binop(wasm::kExprI32Add, baseOffset, | 
 |  2772                  jsgraph()->Int32Constant(offset)); | 
 |  2773   } | 
 |  2774 } | 
 |  2775  | 
 |  2776 Node* WasmGraphBuilder::BuildUnalignedStore(MachineType memtype, Node* index, | 
 |  2777                                             uint32_t offset, uint32_t alignment, | 
 |  2778                                             Node* val) { | 
 |  2779   Node* store; | 
 |  2780   Node* newValue; | 
 |  2781  | 
 |  2782   wasm::WasmOpcode shiftOpcode; | 
 |  2783  | 
 |  2784   Node* shiftConst; | 
 |  2785   bool extendTo64Bit = false; | 
 |  2786   bool isFloat = IsFloatingPoint(memtype.representation()); | 
 |  2787   int stride = 1 << ElementSizeLog2Of( | 
 |  2788                    GetTypeForUnalignedAccess(alignment).representation()); | 
 |  2789   int numberOfBytes = 1 << ElementSizeLog2Of(memtype.representation()); | 
 |  2790   int numberOfLoads = numberOfBytes / stride; | 
 |  2791  | 
 |  2792   DCHECK(numberOfBytes % stride == 0); | 
 |  2793   DCHECK(numberOfLoads >= 2); | 
 |  2794  | 
 |  2795   StoreRepresentation rep(GetTypeForUnalignedAccess(alignment).representation(), | 
 |  2796                           kNoWriteBarrier); | 
 |  2797  | 
 |  2798   if (ElementSizeLog2Of(memtype.representation()) <= 2) { | 
 |  2799     shiftOpcode = wasm::kExprI32ShrU; | 
 |  2800     shiftConst = jsgraph()->Int32Constant(8 * stride); | 
 |  2801   } else { | 
 |  2802     shiftOpcode = wasm::kExprI64ShrU; | 
 |  2803     shiftConst = jsgraph()->Int64Constant(8 * stride); | 
 |  2804     extendTo64Bit = true; | 
 |  2805   } | 
 |  2806  | 
 |  2807   newValue = val; | 
 |  2808   if (isFloat) { | 
 |  2809     switch (memtype.representation()) { | 
 |  2810       case MachineRepresentation::kFloat64: | 
 |  2811         newValue = Unop(wasm::kExprI64ReinterpretF64, val); | 
 |  2812         break; | 
 |  2813       case MachineRepresentation::kFloat32: | 
 |  2814         newValue = Unop(wasm::kExprI32ReinterpretF32, val); | 
 |  2815         break; | 
 |  2816       default: | 
 |  2817         UNREACHABLE(); | 
 |  2818     } | 
 |  2819   } | 
 |  2820  | 
 |  2821   Node* baseOffset = MemBuffer(offset); | 
 |  2822  | 
 |  2823   for (int i = 0; i < numberOfBytes - stride; i += stride) { | 
 |  2824     store = graph()->NewNode( | 
 |  2825         jsgraph()->machine()->Store(rep), | 
 |  2826         GetUnalignedStoreOffsetNode(baseOffset, numberOfBytes, stride, i), | 
 |  2827         index, | 
 |  2828         extendTo64Bit ? Unop(wasm::kExprI32ConvertI64, newValue) : newValue, | 
 |  2829         *effect_, *control_); | 
 |  2830     newValue = Binop(shiftOpcode, newValue, shiftConst); | 
 |  2831     *effect_ = store; | 
 |  2832   } | 
 |  2833   store = graph()->NewNode( | 
 |  2834       jsgraph()->machine()->Store(rep), | 
 |  2835       GetUnalignedStoreOffsetNode(baseOffset, numberOfBytes, stride, | 
 |  2836                                   numberOfBytes - stride), | 
 |  2837       index, | 
 |  2838       extendTo64Bit ? Unop(wasm::kExprI32ConvertI64, newValue) : newValue, | 
 |  2839       *effect_, *control_); | 
 |  2840   *effect_ = store; | 
 |  2841   return val; | 
 |  2842 } | 
 |  2843  | 
|  2630 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |  2844 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, | 
|  2631                                  uint32_t offset, Node* val, |  2845                                  uint32_t offset, uint32_t alignment, Node* val, | 
|  2632                                  wasm::WasmCodePosition position) { |  2846                                  wasm::WasmCodePosition position) { | 
|  2633   Node* store; |  2847   Node* store; | 
|  2634   if (module_ && module_->asm_js()) { |  2848   if (module_ && module_->asm_js()) { | 
|  2635     // asm.js semantics use CheckedStore (i.e. ignore OOB writes). |  2849     // asm.js semantics use CheckedStore (i.e. ignore OOB writes). | 
|  2636     DCHECK_EQ(0, offset); |  2850     DCHECK_EQ(0, offset); | 
|  2637     const Operator* op = |  2851     const Operator* op = | 
|  2638         jsgraph()->machine()->CheckedStore(memtype.representation()); |  2852         jsgraph()->machine()->CheckedStore(memtype.representation()); | 
|  2639     store = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), val, *effect_, |  2853     store = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), val, *effect_, | 
|  2640                              *control_); |  2854                              *control_); | 
 |  2855     *effect_ = store; | 
|  2641   } else { |  2856   } else { | 
|  2642     // WASM semantics throw on OOB. Introduce explicit bounds check. |  2857     // WASM semantics throw on OOB. Introduce explicit bounds check. | 
|  2643     BoundsCheckMem(memtype, index, offset, position); |  2858     BoundsCheckMem(memtype, index, offset, position); | 
|  2644     StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |  2859     StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 
|  2645     store = |  2860     bool aligned = alignment >= ElementSizeLog2Of(memtype.representation()); | 
|  2646         graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), |  2861  | 
|  2647                          index, val, *effect_, *control_); |  2862     if (aligned || | 
 |  2863         jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { | 
 |  2864       StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 
 |  2865       store = | 
 |  2866           graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), | 
 |  2867                            index, val, *effect_, *control_); | 
 |  2868       *effect_ = store; | 
 |  2869     } else { | 
 |  2870       store = BuildUnalignedStore(memtype, index, offset, alignment, val); | 
 |  2871     } | 
|  2648   } |  2872   } | 
|  2649   *effect_ = store; |  2873  | 
|  2650   return store; |  2874   return store; | 
|  2651 } |  2875 } | 
|  2652  |  2876  | 
|  2653  |  2877  | 
|  2654 void WasmGraphBuilder::PrintDebugName(Node* node) { |  2878 void WasmGraphBuilder::PrintDebugName(Node* node) { | 
|  2655   PrintF("#%d:%s", node->id(), node->op()->mnemonic()); |  2879   PrintF("#%d:%s", node->id(), node->op()->mnemonic()); | 
|  2656 } |  2880 } | 
|  2657  |  2881  | 
|  2658  |  2882  | 
|  2659 Node* WasmGraphBuilder::String(const char* string) { |  2883 Node* WasmGraphBuilder::String(const char* string) { | 
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2870     double* decode_ms) { |  3094     double* decode_ms) { | 
|  2871   base::ElapsedTimer decode_timer; |  3095   base::ElapsedTimer decode_timer; | 
|  2872   if (FLAG_trace_wasm_decode_time) { |  3096   if (FLAG_trace_wasm_decode_time) { | 
|  2873     decode_timer.Start(); |  3097     decode_timer.Start(); | 
|  2874   } |  3098   } | 
|  2875   // Create a TF graph during decoding. |  3099   // Create a TF graph during decoding. | 
|  2876   Graph* graph = new (zone) Graph(zone); |  3100   Graph* graph = new (zone) Graph(zone); | 
|  2877   CommonOperatorBuilder* common = new (zone) CommonOperatorBuilder(zone); |  3101   CommonOperatorBuilder* common = new (zone) CommonOperatorBuilder(zone); | 
|  2878   MachineOperatorBuilder* machine = new (zone) MachineOperatorBuilder( |  3102   MachineOperatorBuilder* machine = new (zone) MachineOperatorBuilder( | 
|  2879       zone, MachineType::PointerRepresentation(), |  3103       zone, MachineType::PointerRepresentation(), | 
|  2880       InstructionSelector::SupportedMachineOperatorFlags()); |  3104       InstructionSelector::SupportedMachineOperatorFlags(), | 
 |  3105       InstructionSelector::AlignmentRequirements()); | 
|  2881   JSGraph* jsgraph = |  3106   JSGraph* jsgraph = | 
|  2882       new (zone) JSGraph(isolate, graph, common, nullptr, nullptr, machine); |  3107       new (zone) JSGraph(isolate, graph, common, nullptr, nullptr, machine); | 
|  2883   SourcePositionTable* source_position_table = |  3108   SourcePositionTable* source_position_table = | 
|  2884       new (zone) SourcePositionTable(graph); |  3109       new (zone) SourcePositionTable(graph); | 
|  2885   WasmGraphBuilder builder(zone, jsgraph, function->sig, source_position_table); |  3110   WasmGraphBuilder builder(zone, jsgraph, function->sig, source_position_table); | 
|  2886   wasm::FunctionBody body = { |  3111   wasm::FunctionBody body = { | 
|  2887       module_env, function->sig, module_env->module->module_start, |  3112       module_env, function->sig, module_env->module->module_start, | 
|  2888       module_env->module->module_start + function->code_start_offset, |  3113       module_env->module->module_start + function->code_start_offset, | 
|  2889       module_env->module->module_start + function->code_end_offset}; |  3114       module_env->module->module_start + function->code_end_offset}; | 
|  2890   wasm::TreeResult result = |  3115   wasm::TreeResult result = | 
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3077                                  const wasm::WasmFunction* function) { |  3302                                  const wasm::WasmFunction* function) { | 
|  3078   WasmCompilationUnit* unit = |  3303   WasmCompilationUnit* unit = | 
|  3079       CreateWasmCompilationUnit(thrower, isolate, module_env, function, 0); |  3304       CreateWasmCompilationUnit(thrower, isolate, module_env, function, 0); | 
|  3080   ExecuteCompilation(unit); |  3305   ExecuteCompilation(unit); | 
|  3081   return FinishCompilation(unit); |  3306   return FinishCompilation(unit); | 
|  3082 } |  3307 } | 
|  3083  |  3308  | 
|  3084 }  // namespace compiler |  3309 }  // namespace compiler | 
|  3085 }  // namespace internal |  3310 }  // namespace internal | 
|  3086 }  // namespace v8 |  3311 }  // namespace v8 | 
| OLD | NEW |