v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-compiler.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <stdlib.h>
29 #include <wchar.h>
30 
31 #include "v8.h"
32 
33 #include "compiler.h"
34 #include "disasm.h"
35 #include "cctest.h"
36 
37 using namespace v8::internal;
38 
39 static MaybeObject* GetGlobalProperty(const char* name) {
40  Isolate* isolate = CcTest::i_isolate();
41  Handle<String> internalized_name =
42  isolate->factory()->InternalizeUtf8String(name);
43  return isolate->context()->global_object()->GetProperty(*internalized_name);
44 }
45 
46 
47 static void SetGlobalProperty(const char* name, Object* value) {
48  Isolate* isolate = CcTest::i_isolate();
49  Handle<Object> object(value, isolate);
50  Handle<String> internalized_name =
51  isolate->factory()->InternalizeUtf8String(name);
52  Handle<JSObject> global(isolate->context()->global_object());
53  Runtime::SetObjectProperty(isolate, global, internalized_name, object, NONE,
54  SLOPPY);
55 }
56 
57 
58 static Handle<JSFunction> Compile(const char* source) {
59  Isolate* isolate = CcTest::i_isolate();
60  Handle<String> source_code(
61  isolate->factory()->NewStringFromUtf8(CStrVector(source)));
62  Handle<SharedFunctionInfo> shared_function =
63  Compiler::CompileScript(source_code,
65  0,
66  0,
67  false,
68  Handle<Context>(isolate->native_context()),
71  return isolate->factory()->NewFunctionFromSharedFunctionInfo(
72  shared_function, isolate->native_context());
73 }
74 
75 
76 static double Inc(Isolate* isolate, int x) {
77  const char* source = "result = %d + 1;";
79  OS::SNPrintF(buffer, source, x);
80 
81  Handle<JSFunction> fun = Compile(buffer.start());
82  if (fun.is_null()) return -1;
83 
84  bool has_pending_exception;
85  Handle<JSObject> global(isolate->context()->global_object());
86  Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception);
87  CHECK(!has_pending_exception);
88  return GetGlobalProperty("result")->ToObjectChecked()->Number();
89 }
90 
91 
92 TEST(Inc) {
95  CHECK_EQ(4.0, Inc(CcTest::i_isolate(), 3));
96 }
97 
98 
99 static double Add(Isolate* isolate, int x, int y) {
100  Handle<JSFunction> fun = Compile("result = x + y;");
101  if (fun.is_null()) return -1;
102 
103  SetGlobalProperty("x", Smi::FromInt(x));
104  SetGlobalProperty("y", Smi::FromInt(y));
105  bool has_pending_exception;
106  Handle<JSObject> global(isolate->context()->global_object());
107  Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception);
108  CHECK(!has_pending_exception);
109  return GetGlobalProperty("result")->ToObjectChecked()->Number();
110 }
111 
112 
113 TEST(Add) {
116  CHECK_EQ(5.0, Add(CcTest::i_isolate(), 2, 3));
117 }
118 
119 
120 static double Abs(Isolate* isolate, int x) {
121  Handle<JSFunction> fun = Compile("if (x < 0) result = -x; else result = x;");
122  if (fun.is_null()) return -1;
123 
124  SetGlobalProperty("x", Smi::FromInt(x));
125  bool has_pending_exception;
126  Handle<JSObject> global(isolate->context()->global_object());
127  Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception);
128  CHECK(!has_pending_exception);
129  return GetGlobalProperty("result")->ToObjectChecked()->Number();
130 }
131 
132 
136  CHECK_EQ(3.0, Abs(CcTest::i_isolate(), -3));
137 }
138 
139 
140 static double Sum(Isolate* isolate, int n) {
141  Handle<JSFunction> fun =
142  Compile("s = 0; while (n > 0) { s += n; n -= 1; }; result = s;");
143  if (fun.is_null()) return -1;
144 
145  SetGlobalProperty("n", Smi::FromInt(n));
146  bool has_pending_exception;
147  Handle<JSObject> global(isolate->context()->global_object());
148  Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception);
149  CHECK(!has_pending_exception);
150  return GetGlobalProperty("result")->ToObjectChecked()->Number();
151 }
152 
153 
154 TEST(Sum) {
157  CHECK_EQ(5050.0, Sum(CcTest::i_isolate(), 100));
158 }
159 
160 
163  v8::Local<v8::Context> context = CcTest::NewContext(PRINT_EXTENSION);
164  v8::Context::Scope context_scope(context);
165  const char* source = "for (n = 0; n < 100; ++n) print(n, 1, 2);";
166  Handle<JSFunction> fun = Compile(source);
167  if (fun.is_null()) return;
168  bool has_pending_exception;
169  Handle<JSObject> global(CcTest::i_isolate()->context()->global_object());
171  CcTest::i_isolate(), fun, global, 0, NULL, &has_pending_exception);
172  CHECK(!has_pending_exception);
173 }
174 
175 
176 // The following test method stems from my coding efforts today. It
177 // tests all the functionality I have added to the compiler today
178 TEST(Stuff) {
181  const char* source =
182  "r = 0;\n"
183  "a = new Object;\n"
184  "if (a == a) r+=1;\n" // 1
185  "if (a != new Object()) r+=2;\n" // 2
186  "a.x = 42;\n"
187  "if (a.x == 42) r+=4;\n" // 4
188  "function foo() { var x = 87; return x; }\n"
189  "if (foo() == 87) r+=8;\n" // 8
190  "function bar() { var x; x = 99; return x; }\n"
191  "if (bar() == 99) r+=16;\n" // 16
192  "function baz() { var x = 1, y, z = 2; y = 3; return x + y + z; }\n"
193  "if (baz() == 6) r+=32;\n" // 32
194  "function Cons0() { this.x = 42; this.y = 87; }\n"
195  "if (new Cons0().x == 42) r+=64;\n" // 64
196  "if (new Cons0().y == 87) r+=128;\n" // 128
197  "function Cons2(x, y) { this.sum = x + y; }\n"
198  "if (new Cons2(3,4).sum == 7) r+=256;"; // 256
199 
200  Handle<JSFunction> fun = Compile(source);
201  CHECK(!fun.is_null());
202  bool has_pending_exception;
203  Handle<JSObject> global(CcTest::i_isolate()->context()->global_object());
205  CcTest::i_isolate(), fun, global, 0, NULL, &has_pending_exception);
206  CHECK(!has_pending_exception);
207  CHECK_EQ(511.0, GetGlobalProperty("r")->ToObjectChecked()->Number());
208 }
209 
210 
211 TEST(UncaughtThrow) {
214 
215  const char* source = "throw 42;";
216  Handle<JSFunction> fun = Compile(source);
217  CHECK(!fun.is_null());
218  bool has_pending_exception;
219  Isolate* isolate = fun->GetIsolate();
220  Handle<JSObject> global(isolate->context()->global_object());
221  Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception);
222  CHECK(has_pending_exception);
223  CHECK_EQ(42.0, isolate->pending_exception()->ToObjectChecked()->Number());
224 }
225 
226 
227 // Tests calling a builtin function from C/C++ code, and the builtin function
228 // performs GC. It creates a stack frame looks like following:
229 // | C (PerformGC) |
230 // | JS-to-C |
231 // | JS |
232 // | C-to-JS |
233 TEST(C2JSFrames) {
234  FLAG_expose_gc = true;
236  v8::Local<v8::Context> context =
237  CcTest::NewContext(PRINT_EXTENSION | GC_EXTENSION);
238  v8::Context::Scope context_scope(context);
239 
240  const char* source = "function foo(a) { gc(), print(a); }";
241 
242  Handle<JSFunction> fun0 = Compile(source);
243  CHECK(!fun0.is_null());
244  Isolate* isolate = fun0->GetIsolate();
245 
246  // Run the generated code to populate the global object with 'foo'.
247  bool has_pending_exception;
248  Handle<JSObject> global(isolate->context()->global_object());
250  isolate, fun0, global, 0, NULL, &has_pending_exception);
251  CHECK(!has_pending_exception);
252 
253  Object* foo_string = isolate->factory()->InternalizeOneByteString(
254  STATIC_ASCII_VECTOR("foo"))->ToObjectChecked();
255  MaybeObject* fun1_object = isolate->context()->global_object()->
256  GetProperty(String::cast(foo_string));
257  Handle<Object> fun1(fun1_object->ToObjectChecked(), isolate);
258  CHECK(fun1->IsJSFunction());
259 
260  Handle<Object> argv[] = { isolate->factory()->InternalizeOneByteString(
261  STATIC_ASCII_VECTOR("hello")) };
262  Execution::Call(isolate,
264  global,
265  ARRAY_SIZE(argv),
266  argv,
267  &has_pending_exception);
268  CHECK(!has_pending_exception);
269 }
270 
271 
272 // Regression 236. Calling InitLineEnds on a Script with undefined
273 // source resulted in crash.
274 TEST(Regression236) {
276  Isolate* isolate = CcTest::i_isolate();
277  Factory* factory = isolate->factory();
279 
280  Handle<Script> script = factory->NewScript(factory->empty_string());
281  script->set_source(CcTest::heap()->undefined_value());
282  CHECK_EQ(-1, GetScriptLineNumber(script, 0));
283  CHECK_EQ(-1, GetScriptLineNumber(script, 100));
284  CHECK_EQ(-1, GetScriptLineNumber(script, -1));
285 }
286 
287 
289  LocalContext context;
291  v8::ScriptOrigin origin =
293  const char function_f[] = "function f() {}";
294  const int max_rows = 1000;
295  const int buffer_size = max_rows + sizeof(function_f);
296  ScopedVector<char> buffer(buffer_size);
297  memset(buffer.start(), '\n', buffer_size - 1);
298  buffer[buffer_size - 1] = '\0';
299 
300  for (int i = 0; i < max_rows; ++i) {
301  if (i > 0)
302  buffer[i - 1] = '\n';
303  OS::MemCopy(&buffer[i], function_f, sizeof(function_f) - 1);
304  v8::Handle<v8::String> script_body =
305  v8::String::NewFromUtf8(CcTest::isolate(), buffer.start());
306  v8::Script::Compile(script_body, &origin)->Run();
308  v8::Local<v8::Function>::Cast(context->Global()->Get(
310  CHECK_EQ(i, f->GetScriptLineNumber());
311  }
312 }
313 
314 
315 // Test that optimized code for different closures is actually shared
316 // immediately by the FastNewClosureStub when run in the same context.
317 TEST(OptimizedCodeSharing) {
318  // Skip test if --cache-optimized-code is not activated by default because
319  // FastNewClosureStub that is baked into the snapshot is incorrect.
320  if (!FLAG_cache_optimized_code) return;
321  FLAG_stress_compaction = false;
322  FLAG_allow_natives_syntax = true;
325  for (int i = 0; i < 10; i++) {
326  LocalContext env;
327  env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"),
329  CompileRun("function MakeClosure() {"
330  " return function() { return x; };"
331  "}"
332  "var closure0 = MakeClosure();"
333  "%DebugPrint(closure0());"
334  "%OptimizeFunctionOnNextCall(closure0);"
335  "%DebugPrint(closure0());"
336  "var closure1 = MakeClosure();"
337  "var closure2 = MakeClosure();");
339  *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure1"))));
341  *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure2"))));
342  CHECK(fun1->IsOptimized()
343  || !CcTest::i_isolate()->use_crankshaft() || !fun1->IsOptimizable());
344  CHECK(fun2->IsOptimized()
345  || !CcTest::i_isolate()->use_crankshaft() || !fun2->IsOptimizable());
346  CHECK_EQ(fun1->code(), fun2->code());
347  }
348 }
349 
350 
351 #ifdef ENABLE_DISASSEMBLER
352 static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj,
353  const char* property_name) {
355  v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name)));
356  return v8::Utils::OpenHandle(*fun);
357 }
358 
359 
360 static void CheckCodeForUnsafeLiteral(Handle<JSFunction> f) {
361  // Create a disassembler with default name lookup.
362  disasm::NameConverter name_converter;
363  disasm::Disassembler d(name_converter);
364 
365  if (f->code()->kind() == Code::FUNCTION) {
366  Address pc = f->code()->instruction_start();
367  int decode_size =
368  Min(f->code()->instruction_size(),
369  static_cast<int>(f->code()->back_edge_table_offset()));
370  Address end = pc + decode_size;
371 
374  Smi* smi = Smi::FromInt(12345678);
375  OS::SNPrintF(smi_hex_buffer, "0x%lx", reinterpret_cast<intptr_t>(smi));
376  while (pc < end) {
377  int num_const = d.ConstantPoolSizeAt(pc);
378  if (num_const >= 0) {
379  pc += (num_const + 1) * kPointerSize;
380  } else {
381  pc += d.InstructionDecode(decode_buffer, pc);
382  CHECK(strstr(decode_buffer.start(), smi_hex_buffer.start()) == NULL);
383  }
384  }
385  }
386 }
387 
388 
389 TEST(SplitConstantsInFullCompiler) {
390  LocalContext context;
392 
393  CompileRun("function f() { a = 12345678 }; f();");
394  CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f"));
395  CompileRun("function f(x) { a = 12345678 + x}; f(1);");
396  CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f"));
397  CompileRun("function f(x) { var arguments = 1; x += 12345678}; f(1);");
398  CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f"));
399  CompileRun("function f(x) { var arguments = 1; x = 12345678}; f(1);");
400  CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f"));
401 }
402 #endif
byte * Address
Definition: globals.h:186
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
#define CHECK_EQ(expected, value)
Definition: checks.h:252
Handle< JSFunction > NewFunctionFromSharedFunctionInfo(Handle< SharedFunctionInfo > function_info, Handle< Context > context, PretenureFlag pretenure=TENURED)
Definition: factory.cc:944
static Handle< SharedFunctionInfo > CompileScript(Handle< String > source, Handle< Object > script_name, int line_offset, int column_offset, bool is_shared_cross_origin, Handle< Context > context, v8::Extension *extension, ScriptDataImpl **cached_data, CachedDataMode cached_data_mode, NativesFlag is_natives_code)
Definition: compiler.cc:917
MaybeObject * pending_exception()
Definition: isolate.h:570
static String * cast(Object *obj)
Local< Value > Get(Handle< Value > key)
Definition: api.cc:3139
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
Handle< Script > NewScript(Handle< String > source)
Definition: factory.cc:699
static i::Heap * heap()
Definition: cctest.h:106
static Local< Integer > New(Isolate *isolate, int32_t value)
Definition: api.cc:6233
#define CHECK(condition)
Definition: checks.h:75
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:196
Factory * factory()
Definition: isolate.h:995
static v8::Local< v8::Context > NewContext(CcTestExtensionFlags extensions, v8::Isolate *isolate=CcTest::isolate())
Definition: cctest.cc:90
GlobalObject * global_object()
Definition: contexts.h:388
Handle< String > NewStringFromUtf8(Vector< const char > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:273
T * start() const
Definition: utils.h:426
static void MemCopy(void *dest, const void *src, size_t size)
Definition: platform.h:399
const int kPointerSize
Definition: globals.h:268
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *script_data=NULL)
Definition: api.cc:1832
Local< Object > Global()
Definition: api.cc:5239
const Register pc
static i::Isolate * i_isolate()
Definition: cctest.h:102
#define STATIC_ASCII_VECTOR(x)
Definition: utils.h:570
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:308
static V8_INLINE Local< T > Cast(Local< S > that)
Definition: v8.h:372
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
MUST_USE_RESULT MaybeObject * GetProperty(Name *key)
Definition: objects-inl.h:1081
bool use_crankshaft() const
Definition: isolate.h:1017
Context * context()
Definition: isolate.h:557
static int SNPrintF(Vector< char > str, const char *format,...)
int GetScriptLineNumber(Handle< Script > script, int code_pos)
Definition: handles.cc:363
static void InitializeVM()
Definition: cctest.h:116
static Handle< Object > Call(Isolate *isolate, Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Definition: execution.cc:153
bool is_null() const
Definition: handles.h:81
Handle< String > InternalizeUtf8String(Vector< const char > str)
Definition: factory.cc:218
T Abs(T a)
Definition: utils.h:241
int GetScriptLineNumber() const
Definition: api.cc:4087
void Print(const v8::FunctionCallbackInfo< v8::Value > &args)
static Handle< Object > SetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr, StrictMode strict_mode)
Definition: runtime.cc:5283
HeapObject * obj
Handle< Context > native_context()
Definition: isolate.cc:1372
T Min(T a, T b)
Definition: utils.h:234
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
#define ARRAY_SIZE(a)
Definition: globals.h:333
Definition: v8.h:124
static v8::Isolate * isolate()
Definition: cctest.h:96
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
Definition: api.cc:5417