• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 the V8 project authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file.
4 
5 #include <cmath>
6 #include <functional>
7 #include <limits>
8 
9 #include "src/base/bits.h"
10 #include "src/base/utils/random-number-generator.h"
11 #include "src/codegen.h"
12 #include "test/cctest/cctest.h"
13 #include "test/cctest/compiler/codegen-tester.h"
14 #include "test/cctest/compiler/graph-builder-tester.h"
15 #include "test/cctest/compiler/value-helper.h"
16 
17 using namespace v8::internal;
18 using namespace v8::internal::compiler;
19 
UpdateMemoryReferences(Handle<Code> code,Address old_base,Address new_base,uint32_t old_size,uint32_t new_size)20 static void UpdateMemoryReferences(Handle<Code> code, Address old_base,
21                                    Address new_base, uint32_t old_size,
22                                    uint32_t new_size) {
23   Isolate* isolate = CcTest::i_isolate();
24   bool modified = false;
25   int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) |
26                   RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
27   for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
28     RelocInfo::Mode mode = it.rinfo()->rmode();
29     if (RelocInfo::IsWasmMemoryReference(mode) ||
30         RelocInfo::IsWasmMemorySizeReference(mode)) {
31       // Patch addresses with change in memory start address
32       it.rinfo()->update_wasm_memory_reference(old_base, new_base, old_size,
33                                                new_size);
34       modified = true;
35     }
36   }
37   if (modified) {
38     Assembler::FlushICache(isolate, code->instruction_start(),
39                            code->instruction_size());
40   }
41 }
42 
43 template <typename CType>
RunLoadStoreRelocation(MachineType rep)44 static void RunLoadStoreRelocation(MachineType rep) {
45   const int kNumElems = 2;
46   CType buffer[kNumElems];
47   CType new_buffer[kNumElems];
48   byte* raw = reinterpret_cast<byte*>(buffer);
49   byte* new_raw = reinterpret_cast<byte*>(new_buffer);
50   for (size_t i = 0; i < sizeof(buffer); i++) {
51     raw[i] = static_cast<byte>((i + sizeof(CType)) ^ 0xAA);
52     new_raw[i] = static_cast<byte>((i + sizeof(CType)) ^ 0xAA);
53   }
54   int32_t OK = 0x29000;
55   RawMachineAssemblerTester<uint32_t> m;
56   Node* base = m.RelocatableIntPtrConstant(reinterpret_cast<intptr_t>(raw),
57                                            RelocInfo::WASM_MEMORY_REFERENCE);
58   Node* base1 = m.RelocatableIntPtrConstant(
59       reinterpret_cast<intptr_t>(raw + sizeof(CType)),
60       RelocInfo::WASM_MEMORY_REFERENCE);
61   Node* index = m.Int32Constant(0);
62   Node* load = m.Load(rep, base, index);
63   m.Store(rep.representation(), base1, index, load, kNoWriteBarrier);
64   m.Return(m.Int32Constant(OK));
65   CHECK(buffer[0] != buffer[1]);
66   CHECK_EQ(OK, m.Call());
67   CHECK(buffer[0] == buffer[1]);
68   m.GenerateCode();
69   Handle<Code> code = m.GetCode();
70   UpdateMemoryReferences(code, raw, new_raw, sizeof(buffer),
71                          sizeof(new_buffer));
72   CHECK(new_buffer[0] != new_buffer[1]);
73   CHECK_EQ(OK, m.Call());
74   CHECK(new_buffer[0] == new_buffer[1]);
75 }
76 
TEST(RunLoadStoreRelocation)77 TEST(RunLoadStoreRelocation) {
78   RunLoadStoreRelocation<int8_t>(MachineType::Int8());
79   RunLoadStoreRelocation<uint8_t>(MachineType::Uint8());
80   RunLoadStoreRelocation<int16_t>(MachineType::Int16());
81   RunLoadStoreRelocation<uint16_t>(MachineType::Uint16());
82   RunLoadStoreRelocation<int32_t>(MachineType::Int32());
83   RunLoadStoreRelocation<uint32_t>(MachineType::Uint32());
84   RunLoadStoreRelocation<void*>(MachineType::AnyTagged());
85   RunLoadStoreRelocation<float>(MachineType::Float32());
86   RunLoadStoreRelocation<double>(MachineType::Float64());
87 }
88 
89 template <typename CType>
RunLoadStoreRelocationOffset(MachineType rep)90 static void RunLoadStoreRelocationOffset(MachineType rep) {
91   RawMachineAssemblerTester<int32_t> r(MachineType::Int32());
92   const int kNumElems = 4;
93   CType buffer[kNumElems];
94   CType new_buffer[kNumElems + 1];
95 
96   for (int32_t x = 0; x < kNumElems; x++) {
97     int32_t y = kNumElems - x - 1;
98     // initialize the buffer with raw data.
99     byte* raw = reinterpret_cast<byte*>(buffer);
100     for (size_t i = 0; i < sizeof(buffer); i++) {
101       raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
102     }
103 
104     RawMachineAssemblerTester<int32_t> m;
105     int32_t OK = 0x29000 + x;
106     Node* base = m.RelocatableIntPtrConstant(reinterpret_cast<intptr_t>(buffer),
107                                              RelocInfo::WASM_MEMORY_REFERENCE);
108     Node* index0 = m.IntPtrConstant(x * sizeof(buffer[0]));
109     Node* load = m.Load(rep, base, index0);
110     Node* index1 = m.IntPtrConstant(y * sizeof(buffer[0]));
111     m.Store(rep.representation(), base, index1, load, kNoWriteBarrier);
112     m.Return(m.Int32Constant(OK));
113 
114     CHECK(buffer[x] != buffer[y]);
115     CHECK_EQ(OK, m.Call());
116     CHECK(buffer[x] == buffer[y]);
117     m.GenerateCode();
118 
119     // Initialize new buffer and set old_buffer to 0
120     byte* new_raw = reinterpret_cast<byte*>(new_buffer);
121     for (size_t i = 0; i < sizeof(buffer); i++) {
122       raw[i] = 0;
123       new_raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
124     }
125 
126     // Perform relocation on generated code
127     Handle<Code> code = m.GetCode();
128     UpdateMemoryReferences(code, raw, new_raw, sizeof(buffer),
129                            sizeof(new_buffer));
130 
131     CHECK(new_buffer[x] != new_buffer[y]);
132     CHECK_EQ(OK, m.Call());
133     CHECK(new_buffer[x] == new_buffer[y]);
134   }
135 }
136 
TEST(RunLoadStoreRelocationOffset)137 TEST(RunLoadStoreRelocationOffset) {
138   RunLoadStoreRelocationOffset<int8_t>(MachineType::Int8());
139   RunLoadStoreRelocationOffset<uint8_t>(MachineType::Uint8());
140   RunLoadStoreRelocationOffset<int16_t>(MachineType::Int16());
141   RunLoadStoreRelocationOffset<uint16_t>(MachineType::Uint16());
142   RunLoadStoreRelocationOffset<int32_t>(MachineType::Int32());
143   RunLoadStoreRelocationOffset<uint32_t>(MachineType::Uint32());
144   RunLoadStoreRelocationOffset<void*>(MachineType::AnyTagged());
145   RunLoadStoreRelocationOffset<float>(MachineType::Float32());
146   RunLoadStoreRelocationOffset<double>(MachineType::Float64());
147 }
148 
TEST(Uint32LessThanRelocation)149 TEST(Uint32LessThanRelocation) {
150   RawMachineAssemblerTester<uint32_t> m;
151   RawMachineLabel within_bounds, out_of_bounds;
152   Node* index = m.Int32Constant(0x200);
153   Node* limit =
154       m.RelocatableInt32Constant(0x200, RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
155   Node* cond = m.AddNode(m.machine()->Uint32LessThan(), index, limit);
156   m.Branch(cond, &within_bounds, &out_of_bounds);
157   m.Bind(&within_bounds);
158   m.Return(m.Int32Constant(0xaced));
159   m.Bind(&out_of_bounds);
160   m.Return(m.Int32Constant(0xdeadbeef));
161   // Check that index is out of bounds with current size
162   CHECK_EQ(0xdeadbeef, m.Call());
163   m.GenerateCode();
164 
165   Handle<Code> code = m.GetCode();
166   UpdateMemoryReferences(code, reinterpret_cast<Address>(1234),
167                          reinterpret_cast<Address>(1234), 0x200, 0x400);
168   // Check that after limit is increased, index is within bounds.
169   CHECK_EQ(0xaced, m.Call());
170 }
171