OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 v8::ScriptCompiler::Source bad_source( | 270 v8::ScriptCompiler::Source bad_source( |
271 v8_str(bad_code), new v8::ScriptCompiler::CachedData( | 271 v8_str(bad_code), new v8::ScriptCompiler::CachedData( |
272 cached_data->data, cached_data->length)); | 272 cached_data->data, cached_data->length)); |
273 v8::Local<v8::Value> result = | 273 v8::Local<v8::Value> result = |
274 v8::ScriptCompiler::Compile(isolate, &bad_source)->Run(); | 274 v8::ScriptCompiler::Compile(isolate, &bad_source)->Run(); |
275 CHECK(result->IsInt32()); | 275 CHECK(result->IsInt32()); |
276 CHECK_EQ(25, result->Int32Value()); | 276 CHECK_EQ(25, result->Int32Value()); |
277 } | 277 } |
278 | 278 |
279 | 279 |
280 TEST(PreparseSymbolDataIsUsed) { | |
281 // This tests that we actually do use the symbol data generated by the | |
282 // preparser. | |
283 | |
284 // Only do one compilation pass in this test (otherwise we will parse the | |
285 // source code again without preparse data and it will fail). | |
286 i::FLAG_crankshaft = false; | |
287 | |
288 // Make preparsing work for short scripts. | |
289 i::FLAG_min_preparse_length = 0; | |
290 | |
291 v8::Isolate* isolate = CcTest::isolate(); | |
292 v8::HandleScope handles(isolate); | |
293 v8::Local<v8::Context> context = v8::Context::New(isolate); | |
294 v8::Context::Scope context_scope(context); | |
295 int marker; | |
296 CcTest::i_isolate()->stack_guard()->SetStackLimit( | |
297 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | |
298 | |
299 // Note that the ( before function makes the function not lazily compiled. | |
300 const char* good_code = | |
301 "(function weird() { var foo = 26; return foo; })()"; | |
302 | |
303 // Insert an undefined identifier. If the preparser data is used, the symbol | |
304 // stream is used instead, and this identifier resolves to "foo". | |
305 const char* bad_code = | |
306 "(function weird() { var foo = 26; return wut; })()"; | |
307 | |
308 v8::ScriptCompiler::Source good_source(v8_str(good_code)); | |
309 v8::ScriptCompiler::Compile(isolate, &good_source, | |
310 v8::ScriptCompiler::kProduceDataToCache); | |
311 | |
312 const v8::ScriptCompiler::CachedData* cached_data = | |
313 good_source.GetCachedData(); | |
314 CHECK(cached_data->data != NULL); | |
315 CHECK_GT(cached_data->length, 0); | |
316 | |
317 // Now compile the erroneous code with the good preparse data. If the preparse | |
318 // data is used, we will see a second occurrence of "foo" instead of the | |
319 // unknown "wut". | |
320 v8::ScriptCompiler::Source bad_source( | |
321 v8_str(bad_code), new v8::ScriptCompiler::CachedData( | |
322 cached_data->data, cached_data->length)); | |
323 v8::Local<v8::Value> result = | |
324 v8::ScriptCompiler::Compile(isolate, &bad_source)->Run(); | |
325 CHECK(result->IsInt32()); | |
326 CHECK_EQ(26, result->Int32Value()); | |
327 } | |
328 | |
329 | |
330 TEST(StandAlonePreParser) { | 280 TEST(StandAlonePreParser) { |
331 v8::V8::Initialize(); | 281 v8::V8::Initialize(); |
332 | 282 |
333 int marker; | 283 int marker; |
334 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 284 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
335 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 285 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
336 | 286 |
337 const char* programs[] = { | 287 const char* programs[] = { |
338 "{label: 42}", | 288 "{label: 42}", |
339 "var x = 42;", | 289 "var x = 42;", |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 | 378 |
429 { | 379 { |
430 const char* source = "var myo = {1: \"foo\"}; myo[1];"; | 380 const char* source = "var myo = {1: \"foo\"}; myo[1];"; |
431 v8::Local<v8::Value> result = PreCompileCompileRun(source); | 381 v8::Local<v8::Value> result = PreCompileCompileRun(source); |
432 CHECK(result->IsString()); | 382 CHECK(result->IsString()); |
433 v8::String::Utf8Value utf8(result); | 383 v8::String::Utf8Value utf8(result); |
434 CHECK_EQ("foo", *utf8); | 384 CHECK_EQ("foo", *utf8); |
435 } | 385 } |
436 } | 386 } |
437 | 387 |
438 namespace v8 { | |
439 namespace internal { | |
440 | |
441 struct CompleteParserRecorderFriend { | |
442 static void FakeWritingSymbolIdInPreParseData(CompleteParserRecorder* log, | |
443 int number) { | |
444 log->WriteNumber(number); | |
445 if (log->symbol_id_ < number + 1) { | |
446 log->symbol_id_ = number + 1; | |
447 } | |
448 } | |
449 }; | |
450 | |
451 } | |
452 } | |
453 | |
454 | |
455 TEST(StoringNumbersInPreParseData) { | |
456 // Symbol IDs are split into chunks of 7 bits for storing. This is a | |
457 // regression test for a bug where a symbol id was incorrectly stored if some | |
458 // of the chunks in the middle were all zeros. | |
459 typedef i::CompleteParserRecorderFriend F; | |
460 i::CompleteParserRecorder log; | |
461 for (int i = 0; i < 18; ++i) { | |
462 F::FakeWritingSymbolIdInPreParseData(&log, 1 << i); | |
463 } | |
464 for (int i = 1; i < 18; ++i) { | |
465 F::FakeWritingSymbolIdInPreParseData(&log, (1 << i) + 1); | |
466 } | |
467 for (int i = 6; i < 18; ++i) { | |
468 F::FakeWritingSymbolIdInPreParseData(&log, (3 << i) + (5 << (i - 6))); | |
469 } | |
470 i::Vector<unsigned> store = log.ExtractData(); | |
471 i::ScriptData script_data(store); | |
472 script_data.Initialize(); | |
473 // Check that we get the same symbols back. | |
474 for (int i = 0; i < 18; ++i) { | |
475 CHECK_EQ(1 << i, script_data.GetSymbolIdentifier()); | |
476 } | |
477 for (int i = 1; i < 18; ++i) { | |
478 CHECK_EQ((1 << i) + 1, script_data.GetSymbolIdentifier()); | |
479 } | |
480 for (int i = 6; i < 18; ++i) { | |
481 CHECK_EQ((3 << i) + (5 << (i - 6)), script_data.GetSymbolIdentifier()); | |
482 } | |
483 } | |
484 | |
485 | 388 |
486 TEST(RegressChromium62639) { | 389 TEST(RegressChromium62639) { |
487 v8::V8::Initialize(); | 390 v8::V8::Initialize(); |
488 i::Isolate* isolate = CcTest::i_isolate(); | 391 i::Isolate* isolate = CcTest::i_isolate(); |
489 | 392 |
490 int marker; | 393 int marker; |
491 isolate->stack_guard()->SetStackLimit( | 394 isolate->stack_guard()->SetStackLimit( |
492 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 395 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
493 | 396 |
494 const char* program = "var x = 'something';\n" | 397 const char* program = "var x = 'something';\n" |
(...skipping 1570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2065 v8::V8::Initialize(); | 1968 v8::V8::Initialize(); |
2066 v8::Isolate* isolate = CcTest::isolate(); | 1969 v8::Isolate* isolate = CcTest::isolate(); |
2067 v8::HandleScope handles(isolate); | 1970 v8::HandleScope handles(isolate); |
2068 | 1971 |
2069 int marker; | 1972 int marker; |
2070 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 1973 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
2071 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 1974 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
2072 | 1975 |
2073 struct TestCase { | 1976 struct TestCase { |
2074 const char* program; | 1977 const char* program; |
2075 int symbols; | |
2076 int functions; | 1978 int functions; |
2077 } test_cases[] = { | 1979 } test_cases[] = { |
2078 // Labels and variables are recorded as symbols. | 1980 // No functions. |
2079 {"{label: 42}", 1, 0}, {"{label: 42; label2: 43}", 2, 0}, | 1981 {"var x = 42;", 0}, |
2080 {"var x = 42;", 1, 0}, {"var x = 42, y = 43;", 2, 0}, | 1982 // Functions. |
2081 {"var x = {y: 1};", 2, 0}, | 1983 {"function foo() {}", 1}, {"function foo() {} function bar() {}", 2}, |
2082 {"var x = {}; x.y = 1", 2, 0}, | 1984 // Getter / setter functions are recorded as functions if they're on the top |
2083 // "get" is recorded as a symbol too. | 1985 // level. |
2084 {"var x = {get foo(){} };", 3, 1}, | 1986 {"var x = {get foo(){} };", 1}, |
2085 // When keywords are used as identifiers, they're logged as symbols, too: | 1987 // Functions insize lazy functions are not recorded. |
2086 {"var x = {if: 1};", 2, 0}, | 1988 {"function lazy() { function a() {} function b() {} function c() {} }", 1}, |
2087 {"var x = {}; x.if = 1", 2, 0}, | 1989 {"function lazy() { var x = {get foo(){} } }", 1}, |
2088 {"var x = {get if(){} };", 3, 1}, | 1990 {NULL, 0} |
2089 // Functions | |
2090 {"function foo() {}", 1, 1}, {"function foo() {} function bar() {}", 2, 2}, | |
2091 // Labels, variables and functions insize lazy functions are not recorded. | |
2092 {"function lazy() { var a, b, c; }", 1, 1}, | |
2093 {"function lazy() { a: 1; b: 2; c: 3; }", 1, 1}, | |
2094 {"function lazy() { function a() {} function b() {} function c() {} }", 1, | |
2095 1}, | |
2096 {NULL, 0, 0} | |
2097 }; | 1991 }; |
2098 | 1992 |
2099 for (int i = 0; test_cases[i].program; i++) { | 1993 for (int i = 0; test_cases[i].program; i++) { |
2100 const char* program = test_cases[i].program; | 1994 const char* program = test_cases[i].program; |
2101 i::Factory* factory = CcTest::i_isolate()->factory(); | 1995 i::Factory* factory = CcTest::i_isolate()->factory(); |
2102 i::Handle<i::String> source = | 1996 i::Handle<i::String> source = |
2103 factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked(); | 1997 factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked(); |
2104 i::Handle<i::Script> script = factory->NewScript(source); | 1998 i::Handle<i::Script> script = factory->NewScript(source); |
2105 i::CompilationInfoWithZone info(script); | 1999 i::CompilationInfoWithZone info(script); |
2106 i::ScriptData* data = NULL; | 2000 i::ScriptData* data = NULL; |
2107 info.SetCachedData(&data, i::PRODUCE_CACHED_DATA); | 2001 info.SetCachedData(&data, i::PRODUCE_CACHED_DATA); |
2108 i::Parser::Parse(&info, true); | 2002 i::Parser::Parse(&info, true); |
2109 CHECK(data); | 2003 CHECK(data); |
2110 CHECK(!data->HasError()); | 2004 CHECK(!data->HasError()); |
2111 | 2005 |
2112 if (data->symbol_count() != test_cases[i].symbols) { | |
2113 i::OS::Print( | |
2114 "Expected preparse data for program:\n" | |
2115 "\t%s\n" | |
2116 "to contain %d symbols, however, received %d symbols.\n", | |
2117 program, test_cases[i].symbols, data->symbol_count()); | |
2118 CHECK(false); | |
2119 } | |
2120 if (data->function_count() != test_cases[i].functions) { | 2006 if (data->function_count() != test_cases[i].functions) { |
2121 i::OS::Print( | 2007 i::OS::Print( |
2122 "Expected preparse data for program:\n" | 2008 "Expected preparse data for program:\n" |
2123 "\t%s\n" | 2009 "\t%s\n" |
2124 "to contain %d functions, however, received %d functions.\n", | 2010 "to contain %d functions, however, received %d functions.\n", |
2125 program, test_cases[i].functions, | 2011 program, test_cases[i].functions, |
2126 data->function_count()); | 2012 data->function_count()); |
2127 CHECK(false); | 2013 CHECK(false); |
2128 } | 2014 } |
2129 } | 2015 } |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2566 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError); | 2452 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError); |
2567 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment, | 2453 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment, |
2568 kError); | 2454 kError); |
2569 | 2455 |
2570 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess); | 2456 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess); |
2571 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError); | 2457 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError); |
2572 | 2458 |
2573 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess); | 2459 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess); |
2574 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError); | 2460 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError); |
2575 } | 2461 } |
OLD | NEW |