| 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 |