| 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 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1373 Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST); | 1373 Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST); |
| 1374 while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) { | 1374 while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) { |
| 1375 count++; | 1375 count++; |
| 1376 object = JSFunction::cast(object)->next_function_link(); | 1376 object = JSFunction::cast(object)->next_function_link(); |
| 1377 } | 1377 } |
| 1378 return count; | 1378 return count; |
| 1379 } | 1379 } |
| 1380 | 1380 |
| 1381 | 1381 |
| 1382 TEST(TestInternalWeakLists) { | 1382 TEST(TestInternalWeakLists) { |
| 1383 FLAG_allow_natives_syntax = true; |
| 1383 v8::V8::Initialize(); | 1384 v8::V8::Initialize(); |
| 1385 Isolate* isolate = CcTest::i_isolate(); |
| 1386 |
| 1387 // TODO(mstarzinger): Test should be resilient against optimization decisions. |
| 1388 if (i::FLAG_always_opt) return; |
| 1389 if (!isolate->use_crankshaft()) return; |
| 1384 | 1390 |
| 1385 // Some flags turn Scavenge collections into Mark-sweep collections | 1391 // Some flags turn Scavenge collections into Mark-sweep collections |
| 1386 // and hence are incompatible with this test case. | 1392 // and hence are incompatible with this test case. |
| 1387 if (FLAG_gc_global || FLAG_stress_compaction) return; | 1393 if (FLAG_gc_global || FLAG_stress_compaction) return; |
| 1388 | 1394 |
| 1389 static const int kNumTestContexts = 10; | 1395 static const int kNumTestContexts = 5; |
| 1396 static const int kNumTestCollections = 3; |
| 1390 | 1397 |
| 1391 Isolate* isolate = CcTest::i_isolate(); | |
| 1392 Heap* heap = isolate->heap(); | |
| 1393 HandleScope scope(isolate); | 1398 HandleScope scope(isolate); |
| 1394 v8::Handle<v8::Context> ctx[kNumTestContexts]; | 1399 v8::Handle<v8::Context> ctx[kNumTestContexts]; |
| 1395 | 1400 |
| 1396 CHECK_EQ(0, CountNativeContexts()); | 1401 CHECK_EQ(0, CountNativeContexts()); |
| 1397 | 1402 |
| 1398 // Create a number of global contests which gets linked together. | 1403 // Create a number of global contests which gets linked together. |
| 1399 for (int i = 0; i < kNumTestContexts; i++) { | 1404 for (int i = 0; i < kNumTestContexts; i++) { |
| 1400 ctx[i] = v8::Context::New(CcTest::isolate()); | 1405 ctx[i] = v8::Context::New(CcTest::isolate()); |
| 1401 | 1406 |
| 1402 // Collect garbage that might have been created by one of the | 1407 // Collect garbage that might have been created by one of the |
| 1403 // installed extensions. | 1408 // installed extensions. |
| 1404 isolate->compilation_cache()->Clear(); | 1409 isolate->compilation_cache()->Clear(); |
| 1405 heap->CollectAllGarbage(Heap::kNoGCFlags); | 1410 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1406 | |
| 1407 bool opt = (FLAG_always_opt && isolate->use_crankshaft()); | |
| 1408 | 1411 |
| 1409 CHECK_EQ(i + 1, CountNativeContexts()); | 1412 CHECK_EQ(i + 1, CountNativeContexts()); |
| 1410 | 1413 |
| 1411 ctx[i]->Enter(); | 1414 ctx[i]->Enter(); |
| 1412 | 1415 |
| 1413 // Create a handle scope so no function objects get stuch in the outer | 1416 // Create a handle scope so no function objects get stuch in the outer |
| 1414 // handle scope | 1417 // handle scope |
| 1415 HandleScope scope(isolate); | 1418 HandleScope scope(isolate); |
| 1416 const char* source = "function f1() { };" | 1419 const char* source = "function f1() { };" |
| 1417 "function f2() { };" | 1420 "function f2() { };" |
| 1418 "function f3() { };" | 1421 "function f3() { };" |
| 1419 "function f4() { };" | 1422 "function f4() { };" |
| 1420 "function f5() { };"; | 1423 "function f5() { };"; |
| 1421 CompileRun(source); | 1424 CompileRun(source); |
| 1422 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[i])); | 1425 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[i])); |
| 1423 CompileRun("f1()"); | 1426 CompileRun("f1(); %OptimizeFunctionOnNextCall(f1); f1()"); |
| 1424 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[i])); | 1427 CHECK_EQ(1, CountOptimizedUserFunctions(ctx[i])); |
| 1425 CompileRun("f2()"); | 1428 CompileRun("f2(); %OptimizeFunctionOnNextCall(f2); f2()"); |
| 1426 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); | 1429 CHECK_EQ(2, CountOptimizedUserFunctions(ctx[i])); |
| 1427 CompileRun("f3()"); | 1430 CompileRun("f3(); %OptimizeFunctionOnNextCall(f3); f3()"); |
| 1428 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); | 1431 CHECK_EQ(3, CountOptimizedUserFunctions(ctx[i])); |
| 1429 CompileRun("f4()"); | 1432 CompileRun("f4(); %OptimizeFunctionOnNextCall(f4); f4()"); |
| 1430 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1433 CHECK_EQ(4, CountOptimizedUserFunctions(ctx[i])); |
| 1431 CompileRun("f5()"); | 1434 CompileRun("f5(); %OptimizeFunctionOnNextCall(f5); f5()"); |
| 1432 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); | 1435 CHECK_EQ(5, CountOptimizedUserFunctions(ctx[i])); |
| 1433 | 1436 |
| 1434 // Remove function f1, and | 1437 // Remove function f1, and |
| 1435 CompileRun("f1=null"); | 1438 CompileRun("f1=null"); |
| 1436 | 1439 |
| 1437 // Scavenge treats these references as strong. | 1440 // Scavenge treats these references as strong. |
| 1438 for (int j = 0; j < 10; j++) { | 1441 for (int j = 0; j < kNumTestCollections; j++) { |
| 1439 CcTest::heap()->CollectGarbage(NEW_SPACE); | 1442 CcTest::heap()->CollectGarbage(NEW_SPACE); |
| 1440 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); | 1443 CHECK_EQ(5, CountOptimizedUserFunctions(ctx[i])); |
| 1441 } | 1444 } |
| 1442 | 1445 |
| 1443 // Mark compact handles the weak references. | 1446 // Mark compact handles the weak references. |
| 1444 isolate->compilation_cache()->Clear(); | 1447 isolate->compilation_cache()->Clear(); |
| 1445 heap->CollectAllGarbage(Heap::kNoGCFlags); | 1448 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1446 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1449 CHECK_EQ(4, CountOptimizedUserFunctions(ctx[i])); |
| 1447 | 1450 |
| 1448 // Get rid of f3 and f5 in the same way. | 1451 // Get rid of f3 and f5 in the same way. |
| 1449 CompileRun("f3=null"); | 1452 CompileRun("f3=null"); |
| 1450 for (int j = 0; j < 10; j++) { | 1453 for (int j = 0; j < kNumTestCollections; j++) { |
| 1451 CcTest::heap()->CollectGarbage(NEW_SPACE); | 1454 CcTest::heap()->CollectGarbage(NEW_SPACE); |
| 1452 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1455 CHECK_EQ(4, CountOptimizedUserFunctions(ctx[i])); |
| 1453 } | 1456 } |
| 1454 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1457 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1455 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); | 1458 CHECK_EQ(3, CountOptimizedUserFunctions(ctx[i])); |
| 1456 CompileRun("f5=null"); | 1459 CompileRun("f5=null"); |
| 1457 for (int j = 0; j < 10; j++) { | 1460 for (int j = 0; j < kNumTestCollections; j++) { |
| 1458 CcTest::heap()->CollectGarbage(NEW_SPACE); | 1461 CcTest::heap()->CollectGarbage(NEW_SPACE); |
| 1459 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); | 1462 CHECK_EQ(3, CountOptimizedUserFunctions(ctx[i])); |
| 1460 } | 1463 } |
| 1461 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1464 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1462 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); | 1465 CHECK_EQ(2, CountOptimizedUserFunctions(ctx[i])); |
| 1463 | 1466 |
| 1464 ctx[i]->Exit(); | 1467 ctx[i]->Exit(); |
| 1465 } | 1468 } |
| 1466 | 1469 |
| 1467 // Force compilation cache cleanup. | 1470 // Force compilation cache cleanup. |
| 1468 CcTest::heap()->NotifyContextDisposed(); | 1471 CcTest::heap()->NotifyContextDisposed(); |
| 1469 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1472 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1470 | 1473 |
| 1471 // Dispose the native contexts one by one. | 1474 // Dispose the native contexts one by one. |
| 1472 for (int i = 0; i < kNumTestContexts; i++) { | 1475 for (int i = 0; i < kNumTestContexts; i++) { |
| 1473 // TODO(dcarney): is there a better way to do this? | 1476 // TODO(dcarney): is there a better way to do this? |
| 1474 i::Object** unsafe = reinterpret_cast<i::Object**>(*ctx[i]); | 1477 i::Object** unsafe = reinterpret_cast<i::Object**>(*ctx[i]); |
| 1475 *unsafe = CcTest::heap()->undefined_value(); | 1478 *unsafe = CcTest::heap()->undefined_value(); |
| 1476 ctx[i].Clear(); | 1479 ctx[i].Clear(); |
| 1477 | 1480 |
| 1478 // Scavenge treats these references as strong. | 1481 // Scavenge treats these references as strong. |
| 1479 for (int j = 0; j < 10; j++) { | 1482 for (int j = 0; j < kNumTestCollections; j++) { |
| 1480 CcTest::heap()->CollectGarbage(i::NEW_SPACE); | 1483 CcTest::heap()->CollectGarbage(i::NEW_SPACE); |
| 1481 CHECK_EQ(kNumTestContexts - i, CountNativeContexts()); | 1484 CHECK_EQ(kNumTestContexts - i, CountNativeContexts()); |
| 1482 } | 1485 } |
| 1483 | 1486 |
| 1484 // Mark compact handles the weak references. | 1487 // Mark compact handles the weak references. |
| 1485 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1488 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1486 CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts()); | 1489 CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts()); |
| 1487 } | 1490 } |
| 1488 | 1491 |
| 1489 CHECK_EQ(0, CountNativeContexts()); | 1492 CHECK_EQ(0, CountNativeContexts()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 if (count == n) isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1526 if (count == n) isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1524 object = Handle<Object>( | 1527 object = Handle<Object>( |
| 1525 Object::cast(JSFunction::cast(*object)->next_function_link()), | 1528 Object::cast(JSFunction::cast(*object)->next_function_link()), |
| 1526 isolate); | 1529 isolate); |
| 1527 } | 1530 } |
| 1528 return count; | 1531 return count; |
| 1529 } | 1532 } |
| 1530 | 1533 |
| 1531 | 1534 |
| 1532 TEST(TestInternalWeakListsTraverseWithGC) { | 1535 TEST(TestInternalWeakListsTraverseWithGC) { |
| 1536 FLAG_allow_natives_syntax = true; |
| 1533 v8::V8::Initialize(); | 1537 v8::V8::Initialize(); |
| 1534 Isolate* isolate = CcTest::i_isolate(); | 1538 Isolate* isolate = CcTest::i_isolate(); |
| 1535 | 1539 |
| 1536 static const int kNumTestContexts = 10; | 1540 // TODO(mstarzinger): Test should be resilient against optimization decisions. |
| 1541 if (i::FLAG_always_opt) return; |
| 1542 if (!isolate->use_crankshaft()) return; |
| 1543 |
| 1544 static const int kNumTestContexts = 5; |
| 1537 | 1545 |
| 1538 HandleScope scope(isolate); | 1546 HandleScope scope(isolate); |
| 1539 v8::Handle<v8::Context> ctx[kNumTestContexts]; | 1547 v8::Handle<v8::Context> ctx[kNumTestContexts]; |
| 1540 | 1548 |
| 1541 CHECK_EQ(0, CountNativeContexts()); | 1549 CHECK_EQ(0, CountNativeContexts()); |
| 1542 | 1550 |
| 1543 // Create an number of contexts and check the length of the weak list both | 1551 // Create an number of contexts and check the length of the weak list both |
| 1544 // with and without GCs while iterating the list. | 1552 // with and without GCs while iterating the list. |
| 1545 for (int i = 0; i < kNumTestContexts; i++) { | 1553 for (int i = 0; i < kNumTestContexts; i++) { |
| 1546 ctx[i] = v8::Context::New(CcTest::isolate()); | 1554 ctx[i] = v8::Context::New(CcTest::isolate()); |
| 1547 CHECK_EQ(i + 1, CountNativeContexts()); | 1555 CHECK_EQ(i + 1, CountNativeContexts()); |
| 1548 CHECK_EQ(i + 1, CountNativeContextsWithGC(isolate, i / 2 + 1)); | 1556 CHECK_EQ(i + 1, CountNativeContextsWithGC(isolate, i / 2 + 1)); |
| 1549 } | 1557 } |
| 1550 | 1558 |
| 1551 bool opt = (FLAG_always_opt && isolate->use_crankshaft()); | |
| 1552 | |
| 1553 // Compile a number of functions the length of the weak list of optimized | 1559 // Compile a number of functions the length of the weak list of optimized |
| 1554 // functions both with and without GCs while iterating the list. | 1560 // functions both with and without GCs while iterating the list. |
| 1555 ctx[0]->Enter(); | 1561 ctx[0]->Enter(); |
| 1556 const char* source = "function f1() { };" | 1562 const char* source = "function f1() { };" |
| 1557 "function f2() { };" | 1563 "function f2() { };" |
| 1558 "function f3() { };" | 1564 "function f3() { };" |
| 1559 "function f4() { };" | 1565 "function f4() { };" |
| 1560 "function f5() { };"; | 1566 "function f5() { };"; |
| 1561 CompileRun(source); | 1567 CompileRun(source); |
| 1562 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[0])); | 1568 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[0])); |
| 1563 CompileRun("f1()"); | 1569 CompileRun("f1(); %OptimizeFunctionOnNextCall(f1); f1()"); |
| 1564 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[0])); | 1570 CHECK_EQ(1, CountOptimizedUserFunctions(ctx[0])); |
| 1565 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); | 1571 CHECK_EQ(1, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); |
| 1566 CompileRun("f2()"); | 1572 CompileRun("f2(); %OptimizeFunctionOnNextCall(f2); f2()"); |
| 1567 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[0])); | 1573 CHECK_EQ(2, CountOptimizedUserFunctions(ctx[0])); |
| 1568 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); | 1574 CHECK_EQ(2, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); |
| 1569 CompileRun("f3()"); | 1575 CompileRun("f3(); %OptimizeFunctionOnNextCall(f3); f3()"); |
| 1570 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[0])); | 1576 CHECK_EQ(3, CountOptimizedUserFunctions(ctx[0])); |
| 1571 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); | 1577 CHECK_EQ(3, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); |
| 1572 CompileRun("f4()"); | 1578 CompileRun("f4(); %OptimizeFunctionOnNextCall(f4); f4()"); |
| 1573 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[0])); | 1579 CHECK_EQ(4, CountOptimizedUserFunctions(ctx[0])); |
| 1574 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 2)); | 1580 CHECK_EQ(4, CountOptimizedUserFunctionsWithGC(ctx[0], 2)); |
| 1575 CompileRun("f5()"); | 1581 CompileRun("f5(); %OptimizeFunctionOnNextCall(f5); f5()"); |
| 1576 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[0])); | 1582 CHECK_EQ(5, CountOptimizedUserFunctions(ctx[0])); |
| 1577 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 4)); | 1583 CHECK_EQ(5, CountOptimizedUserFunctionsWithGC(ctx[0], 4)); |
| 1578 | 1584 |
| 1579 ctx[0]->Exit(); | 1585 ctx[0]->Exit(); |
| 1580 } | 1586 } |
| 1581 | 1587 |
| 1582 | 1588 |
| 1583 TEST(TestSizeOfObjects) { | 1589 TEST(TestSizeOfObjects) { |
| 1584 v8::V8::Initialize(); | 1590 v8::V8::Initialize(); |
| 1585 | 1591 |
| 1586 // Get initial heap size after several full GCs, which will stabilize | 1592 // Get initial heap size after several full GCs, which will stabilize |
| 1587 // the heap size and return with sweeping finished completely. | 1593 // the heap size and return with sweeping finished completely. |
| (...skipping 2441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4029 return result; | 4035 return result; |
| 4030 } | 4036 } |
| 4031 | 4037 |
| 4032 | 4038 |
| 4033 TEST(NextCodeLinkIsWeak) { | 4039 TEST(NextCodeLinkIsWeak) { |
| 4034 i::FLAG_allow_natives_syntax = true; | 4040 i::FLAG_allow_natives_syntax = true; |
| 4035 CcTest::InitializeVM(); | 4041 CcTest::InitializeVM(); |
| 4036 Isolate* isolate = CcTest::i_isolate(); | 4042 Isolate* isolate = CcTest::i_isolate(); |
| 4037 v8::internal::Heap* heap = CcTest::heap(); | 4043 v8::internal::Heap* heap = CcTest::heap(); |
| 4038 | 4044 |
| 4045 // TODO(titzer): Test should be resilient against optimization decisions. |
| 4046 if (i::FLAG_always_opt) return; |
| 4039 if (!isolate->use_crankshaft()) return; | 4047 if (!isolate->use_crankshaft()) return; |
| 4048 |
| 4040 HandleScope outer_scope(heap->isolate()); | 4049 HandleScope outer_scope(heap->isolate()); |
| 4041 Handle<Code> code; | 4050 Handle<Code> code; |
| 4042 heap->CollectAllAvailableGarbage(); | 4051 heap->CollectAllAvailableGarbage(); |
| 4043 int code_chain_length_before, code_chain_length_after; | 4052 int code_chain_length_before, code_chain_length_after; |
| 4044 { | 4053 { |
| 4045 HandleScope scope(heap->isolate()); | 4054 HandleScope scope(heap->isolate()); |
| 4046 Handle<JSFunction> mortal = OptimizeDummyFunction("mortal"); | 4055 Handle<JSFunction> mortal = OptimizeDummyFunction("mortal"); |
| 4047 Handle<JSFunction> immortal = OptimizeDummyFunction("immortal"); | 4056 Handle<JSFunction> immortal = OptimizeDummyFunction("immortal"); |
| 4048 CHECK_EQ(immortal->code()->next_code_link(), mortal->code()); | 4057 CHECK_EQ(immortal->code()->next_code_link(), mortal->code()); |
| 4049 code_chain_length_before = GetCodeChainLength(immortal->code()); | 4058 code_chain_length_before = GetCodeChainLength(immortal->code()); |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4408 #ifdef DEBUG | 4417 #ifdef DEBUG |
| 4409 TEST(PathTracer) { | 4418 TEST(PathTracer) { |
| 4410 CcTest::InitializeVM(); | 4419 CcTest::InitializeVM(); |
| 4411 v8::HandleScope scope(CcTest::isolate()); | 4420 v8::HandleScope scope(CcTest::isolate()); |
| 4412 | 4421 |
| 4413 v8::Local<v8::Value> result = CompileRun("'abc'"); | 4422 v8::Local<v8::Value> result = CompileRun("'abc'"); |
| 4414 Handle<Object> o = v8::Utils::OpenHandle(*result); | 4423 Handle<Object> o = v8::Utils::OpenHandle(*result); |
| 4415 CcTest::i_isolate()->heap()->TracePathToObject(*o); | 4424 CcTest::i_isolate()->heap()->TracePathToObject(*o); |
| 4416 } | 4425 } |
| 4417 #endif // DEBUG | 4426 #endif // DEBUG |
| OLD | NEW |