| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 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 | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "src/v8.h" | 
|  | 6 | 
|  | 7 #include "src/compiler/pipeline.h" | 
|  | 8 #include "src/handles.h" | 
|  | 9 #include "src/interpreter/bytecode-generator.h" | 
|  | 10 #include "src/interpreter/interpreter.h" | 
|  | 11 #include "src/isolate.h" | 
|  | 12 #include "src/parsing/parser.h" | 
|  | 13 #include "test/cctest/cctest.h" | 
|  | 14 #include "test/cctest/interpreter/source-position-matcher.h" | 
|  | 15 | 
|  | 16 namespace v8 { | 
|  | 17 namespace internal { | 
|  | 18 namespace interpreter { | 
|  | 19 | 
|  | 20 // Flags enabling optimizations that change generated bytecode array. | 
|  | 21 // Format is <command-line flag> <flag name> <bit index> | 
|  | 22 #define OPTIMIZATION_FLAGS(V)      \ | 
|  | 23   V(FLAG_ignition_reo, kUseReo, 0) \ | 
|  | 24   V(FLAG_ignition_peephole, kUsePeephole, 1) | 
|  | 25 | 
|  | 26 #define DECLARE_BIT(_, Name, BitIndex) static const int Name = 1 << BitIndex; | 
|  | 27 OPTIMIZATION_FLAGS(DECLARE_BIT) | 
|  | 28 #undef DECLARE_BIT | 
|  | 29 | 
|  | 30 // Test cases source positions are checked for. Please ensure all | 
|  | 31 // combinations of flags are present here. This is done manually | 
|  | 32 // because it provides easier to comprehend failure case for humans. | 
|  | 33 #define TEST_CASES(V)                            \ | 
|  | 34   V(UsingReo, kUseReo)                           \ | 
|  | 35   V(UsingReoAndPeephole, kUseReo | kUsePeephole) \ | 
|  | 36   V(UsingPeephole, kUsePeephole) | 
|  | 37 | 
|  | 38 static const char* kTestScripts[] = { | 
|  | 39     "var x = (y = 3) + (x = y); return x + y;", | 
|  | 40 | 
|  | 41     "var x = 55;\n" | 
|  | 42     "var y = x + (x = 1) + (x = 2) + (x = 3);\n" | 
|  | 43     "return y;", | 
|  | 44 | 
|  | 45     "var x = 10; return x >>> 3;", | 
|  | 46 | 
|  | 47     "var x = 0; return x || (1, 2, 3);", | 
|  | 48 | 
|  | 49     "return a || (a, b, a, b, c = 5, 3); ", | 
|  | 50 | 
|  | 51     "var a = 3; var b = 4; a = b; b = a; a = b; return a;", | 
|  | 52 | 
|  | 53     "var a = 1; return [[a, 2], [a + 2]];", | 
|  | 54 | 
|  | 55     "var a = 1; if (a || a < 0) { return 1; }", | 
|  | 56 | 
|  | 57     "var b;" | 
|  | 58     "b = a.name;" | 
|  | 59     "b = a.name;" | 
|  | 60     "a.name = a;" | 
|  | 61     "b = a.name;" | 
|  | 62     "a.name = a;" | 
|  | 63     "return b;", | 
|  | 64 | 
|  | 65     "var sum = 0;\n" | 
|  | 66     "outer: {\n" | 
|  | 67     "  for (var x = 0; x < 10; ++x) {\n" | 
|  | 68     "    for (var y = 0; y < 3; ++y) {\n" | 
|  | 69     "      ++sum;\n" | 
|  | 70     "      if (x + y == 12) { break outer; }\n" | 
|  | 71     "    }\n" | 
|  | 72     "  }\n" | 
|  | 73     "}\n" | 
|  | 74     "return sum;\n", | 
|  | 75 | 
|  | 76     "var a = 1;" | 
|  | 77     "switch (a) {" | 
|  | 78     "  case 1: return a * a + 1;" | 
|  | 79     "  case 1: break;" | 
|  | 80     "  case 2: return (a = 3) * a + (a = 4);" | 
|  | 81     "  case 3:" | 
|  | 82     "}" | 
|  | 83     "return a;", | 
|  | 84 | 
|  | 85     "for (var p of [0, 1, 2]) {}", | 
|  | 86 | 
|  | 87     "var x = { 'a': 1, 'b': 2 };" | 
|  | 88     "for (x['a'] of [1,2,3]) { return x['a']; }", | 
|  | 89 | 
|  | 90     "while (x == 4) {\n" | 
|  | 91     "  var y = x + 1;\n" | 
|  | 92     "  if (y == 2) break;\n" | 
|  | 93     "  for (z['a'] of [0]) {\n" | 
|  | 94     "    x += (x *= 3) + y;" | 
|  | 95     "  }\n" | 
|  | 96     "}\n", | 
|  | 97 | 
|  | 98     "function g(a, b) { return a.func(b + b, b); }\n" | 
|  | 99     "g(new (function Obj() { this.func = function() { return; }})(), 1)\n"}; | 
|  | 100 | 
|  | 101 class OptimizedBytecodeSourcePositionTester final { | 
|  | 102  public: | 
|  | 103   explicit OptimizedBytecodeSourcePositionTester(Isolate* isolate) | 
|  | 104       : isolate_(isolate) { | 
|  | 105     SaveOptimizationFlags(); | 
|  | 106     saved_flag_ignition_ = FLAG_ignition; | 
|  | 107     FLAG_ignition = true; | 
|  | 108     saved_flag_always_opt_ = FLAG_always_opt; | 
|  | 109     FLAG_always_opt = false; | 
|  | 110   } | 
|  | 111 | 
|  | 112   ~OptimizedBytecodeSourcePositionTester() { | 
|  | 113     RestoreOptimizationFlags(); | 
|  | 114     FLAG_ignition = saved_flag_ignition_; | 
|  | 115     FLAG_always_opt = saved_flag_always_opt_; | 
|  | 116   } | 
|  | 117 | 
|  | 118   bool SourcePositionsMatch(int optimization_bitmap, const char* function_body, | 
|  | 119                             const char* function_decl_params = "", | 
|  | 120                             const char* function_args = ""); | 
|  | 121 | 
|  | 122  private: | 
|  | 123   Handle<BytecodeArray> MakeBytecode(int optimization_bitmap, | 
|  | 124                                      const char* function_body, | 
|  | 125                                      const char* function_decl_params, | 
|  | 126                                      const char* function_args); | 
|  | 127   static std::string MakeFunctionName(int optimization_bitmap); | 
|  | 128   static std::string MakeScript(const char* function_name, | 
|  | 129                                 const char* function_body, | 
|  | 130                                 const char* function_decl_params, | 
|  | 131                                 const char* function_args); | 
|  | 132 | 
|  | 133   void SetOptimizationFlags(int optimization_bitmap); | 
|  | 134   void SaveOptimizationFlags(); | 
|  | 135   void RestoreOptimizationFlags(); | 
|  | 136 | 
|  | 137   Isolate* isolate() const { return isolate_; } | 
|  | 138 | 
|  | 139   Isolate* isolate_; | 
|  | 140   int saved_optimization_bitmap_; | 
|  | 141   bool saved_flag_ignition_; | 
|  | 142   bool saved_flag_always_opt_; | 
|  | 143 }; | 
|  | 144 | 
|  | 145 // static | 
|  | 146 std::string OptimizedBytecodeSourcePositionTester::MakeFunctionName( | 
|  | 147     int optimization_bitmap) { | 
|  | 148   std::ostringstream os; | 
|  | 149   os << "test_function_" << optimization_bitmap; | 
|  | 150   return os.str(); | 
|  | 151 } | 
|  | 152 | 
|  | 153 // static | 
|  | 154 std::string OptimizedBytecodeSourcePositionTester::MakeScript( | 
|  | 155     const char* function_name, const char* function_body, | 
|  | 156     const char* function_decl_params, const char* function_args) { | 
|  | 157   std::ostringstream os; | 
|  | 158   os << "function " << function_name << "(" << function_decl_params << ") {"; | 
|  | 159   os << function_body; | 
|  | 160   os << "}"; | 
|  | 161   os << function_name << "(" << function_args << ");"; | 
|  | 162   return os.str(); | 
|  | 163 } | 
|  | 164 | 
|  | 165 Handle<BytecodeArray> OptimizedBytecodeSourcePositionTester::MakeBytecode( | 
|  | 166     int optimization_bitmap, const char* function_body, | 
|  | 167     const char* function_decl_params, const char* function_args) { | 
|  | 168   std::string function_name = MakeFunctionName(optimization_bitmap); | 
|  | 169   std::string script = MakeScript(function_name.c_str(), function_body, | 
|  | 170                                   function_decl_params, function_args); | 
|  | 171   SetOptimizationFlags(optimization_bitmap); | 
|  | 172   CompileRun(script.c_str()); | 
|  | 173 | 
|  | 174   Local<Function> api_function = | 
|  | 175       Local<Function>::Cast(CcTest::global() | 
|  | 176                                 ->Get(CcTest::isolate()->GetCurrentContext(), | 
|  | 177                                       v8_str(function_name.c_str())) | 
|  | 178                                 .ToLocalChecked()); | 
|  | 179   Handle<JSFunction> function = | 
|  | 180       Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function)); | 
|  | 181   return handle(function->shared()->bytecode_array()); | 
|  | 182 } | 
|  | 183 | 
|  | 184 void OptimizedBytecodeSourcePositionTester::SetOptimizationFlags( | 
|  | 185     int optimization_bitmap) { | 
|  | 186 #define SET_FLAG(V8Flag, BitName, _) \ | 
|  | 187   V8Flag = (optimization_bitmap & BitName) ? true : false; | 
|  | 188   OPTIMIZATION_FLAGS(SET_FLAG) | 
|  | 189 #undef SET_FLAG | 
|  | 190 } | 
|  | 191 | 
|  | 192 void OptimizedBytecodeSourcePositionTester::SaveOptimizationFlags() { | 
|  | 193   saved_optimization_bitmap_ = 0; | 
|  | 194 #define SAVE_FLAG(V8Flag, BitName, _) \ | 
|  | 195   if (V8Flag) saved_optimization_bitmap_ |= BitName; | 
|  | 196 #undef SET_FLAG | 
|  | 197 } | 
|  | 198 | 
|  | 199 void OptimizedBytecodeSourcePositionTester::RestoreOptimizationFlags() { | 
|  | 200   SetOptimizationFlags(saved_optimization_bitmap_); | 
|  | 201 } | 
|  | 202 | 
|  | 203 bool OptimizedBytecodeSourcePositionTester::SourcePositionsMatch( | 
|  | 204     int optimization_bitmap, const char* function_body, | 
|  | 205     const char* function_decl_params, const char* function_args) { | 
|  | 206   Handle<BytecodeArray> unoptimized_bytecode = | 
|  | 207       MakeBytecode(0, function_body, function_decl_params, function_args); | 
|  | 208   Handle<BytecodeArray> optimized_bytecode = MakeBytecode( | 
|  | 209       optimization_bitmap, function_body, function_decl_params, function_args); | 
|  | 210   SourcePositionMatcher matcher; | 
|  | 211   if (!matcher.Match(unoptimized_bytecode, optimized_bytecode)) { | 
|  | 212     return false; | 
|  | 213   } | 
|  | 214   return true; | 
|  | 215 } | 
|  | 216 | 
|  | 217 void TestSourcePositionsEquivalent(int optimization_bitmap) { | 
|  | 218   HandleAndZoneScope handles; | 
|  | 219   // Ensure handler table is generated. | 
|  | 220   handles.main_isolate()->interpreter()->Initialize(); | 
|  | 221 | 
|  | 222   OptimizedBytecodeSourcePositionTester tester(handles.main_isolate()); | 
|  | 223   for (auto test_script : kTestScripts) { | 
|  | 224     CHECK(tester.SourcePositionsMatch(optimization_bitmap, test_script)); | 
|  | 225   } | 
|  | 226 } | 
|  | 227 | 
|  | 228 #define MAKE_TEST(Name, Bitmap)               \ | 
|  | 229   TEST(TestSourcePositionsEquivalent##Name) { \ | 
|  | 230     TestSourcePositionsEquivalent(Bitmap);    \ | 
|  | 231   } | 
|  | 232 TEST_CASES(MAKE_TEST) | 
|  | 233 #undef MAKE_TEST | 
|  | 234 | 
|  | 235 }  // namespace interpreter | 
|  | 236 }  // namespace internal | 
|  | 237 }  // namespace v8 | 
| OLD | NEW | 
|---|