| 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 1379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1390 Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST); | 1390 Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST); |
| 1391 while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) { | 1391 while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) { |
| 1392 count++; | 1392 count++; |
| 1393 object = JSFunction::cast(object)->next_function_link(); | 1393 object = JSFunction::cast(object)->next_function_link(); |
| 1394 } | 1394 } |
| 1395 return count; | 1395 return count; |
| 1396 } | 1396 } |
| 1397 | 1397 |
| 1398 | 1398 |
| 1399 TEST(TestInternalWeakLists) { | 1399 TEST(TestInternalWeakLists) { |
| 1400 FLAG_allow_natives_syntax = true; |
| 1400 v8::V8::Initialize(); | 1401 v8::V8::Initialize(); |
| 1402 Isolate* isolate = CcTest::i_isolate(); |
| 1403 |
| 1404 // TODO(mstarzinger): Test should be resilient against optimization decisions. |
| 1405 if (i::FLAG_always_opt) return; |
| 1406 if (!isolate->use_crankshaft()) return; |
| 1401 | 1407 |
| 1402 // Some flags turn Scavenge collections into Mark-sweep collections | 1408 // Some flags turn Scavenge collections into Mark-sweep collections |
| 1403 // and hence are incompatible with this test case. | 1409 // and hence are incompatible with this test case. |
| 1404 if (FLAG_gc_global || FLAG_stress_compaction) return; | 1410 if (FLAG_gc_global || FLAG_stress_compaction) return; |
| 1405 | 1411 |
| 1406 static const int kNumTestContexts = 10; | 1412 static const int kNumTestContexts = 5; |
| 1413 static const int kNumTestCollections = 3; |
| 1407 | 1414 |
| 1408 Isolate* isolate = CcTest::i_isolate(); | |
| 1409 Heap* heap = isolate->heap(); | |
| 1410 HandleScope scope(isolate); | 1415 HandleScope scope(isolate); |
| 1411 v8::Handle<v8::Context> ctx[kNumTestContexts]; | 1416 v8::Handle<v8::Context> ctx[kNumTestContexts]; |
| 1412 | 1417 |
| 1413 CHECK_EQ(0, CountNativeContexts()); | 1418 CHECK_EQ(0, CountNativeContexts()); |
| 1414 | 1419 |
| 1415 // Create a number of global contests which gets linked together. | 1420 // Create a number of global contests which gets linked together. |
| 1416 for (int i = 0; i < kNumTestContexts; i++) { | 1421 for (int i = 0; i < kNumTestContexts; i++) { |
| 1417 ctx[i] = v8::Context::New(CcTest::isolate()); | 1422 ctx[i] = v8::Context::New(CcTest::isolate()); |
| 1418 | 1423 |
| 1419 // Collect garbage that might have been created by one of the | 1424 // Collect garbage that might have been created by one of the |
| 1420 // installed extensions. | 1425 // installed extensions. |
| 1421 isolate->compilation_cache()->Clear(); | 1426 isolate->compilation_cache()->Clear(); |
| 1422 heap->CollectAllGarbage(Heap::kNoGCFlags); | 1427 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1423 | |
| 1424 bool opt = (FLAG_always_opt && isolate->use_crankshaft()); | |
| 1425 | 1428 |
| 1426 CHECK_EQ(i + 1, CountNativeContexts()); | 1429 CHECK_EQ(i + 1, CountNativeContexts()); |
| 1427 | 1430 |
| 1428 ctx[i]->Enter(); | 1431 ctx[i]->Enter(); |
| 1429 | 1432 |
| 1430 // Create a handle scope so no function objects get stuch in the outer | 1433 // Create a handle scope so no function objects get stuch in the outer |
| 1431 // handle scope | 1434 // handle scope |
| 1432 HandleScope scope(isolate); | 1435 HandleScope scope(isolate); |
| 1433 const char* source = "function f1() { };" | 1436 const char* source = "function f1() { };" |
| 1434 "function f2() { };" | 1437 "function f2() { };" |
| 1435 "function f3() { };" | 1438 "function f3() { };" |
| 1436 "function f4() { };" | 1439 "function f4() { };" |
| 1437 "function f5() { };"; | 1440 "function f5() { };"; |
| 1438 CompileRun(source); | 1441 CompileRun(source); |
| 1439 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[i])); | 1442 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[i])); |
| 1440 CompileRun("f1()"); | 1443 CompileRun("f1(); %OptimizeFunctionOnNextCall(f1); f1()"); |
| 1441 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[i])); | 1444 CHECK_EQ(1, CountOptimizedUserFunctions(ctx[i])); |
| 1442 CompileRun("f2()"); | 1445 CompileRun("f2(); %OptimizeFunctionOnNextCall(f2); f2()"); |
| 1443 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); | 1446 CHECK_EQ(2, CountOptimizedUserFunctions(ctx[i])); |
| 1444 CompileRun("f3()"); | 1447 CompileRun("f3(); %OptimizeFunctionOnNextCall(f3); f3()"); |
| 1445 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); | 1448 CHECK_EQ(3, CountOptimizedUserFunctions(ctx[i])); |
| 1446 CompileRun("f4()"); | 1449 CompileRun("f4(); %OptimizeFunctionOnNextCall(f4); f4()"); |
| 1447 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1450 CHECK_EQ(4, CountOptimizedUserFunctions(ctx[i])); |
| 1448 CompileRun("f5()"); | 1451 CompileRun("f5(); %OptimizeFunctionOnNextCall(f5); f5()"); |
| 1449 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); | 1452 CHECK_EQ(5, CountOptimizedUserFunctions(ctx[i])); |
| 1450 | 1453 |
| 1451 // Remove function f1, and | 1454 // Remove function f1, and |
| 1452 CompileRun("f1=null"); | 1455 CompileRun("f1=null"); |
| 1453 | 1456 |
| 1454 // Scavenge treats these references as strong. | 1457 // Scavenge treats these references as strong. |
| 1455 for (int j = 0; j < 10; j++) { | 1458 for (int j = 0; j < kNumTestCollections; j++) { |
| 1456 CcTest::heap()->CollectGarbage(NEW_SPACE); | 1459 CcTest::heap()->CollectGarbage(NEW_SPACE); |
| 1457 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); | 1460 CHECK_EQ(5, CountOptimizedUserFunctions(ctx[i])); |
| 1458 } | 1461 } |
| 1459 | 1462 |
| 1460 // Mark compact handles the weak references. | 1463 // Mark compact handles the weak references. |
| 1461 isolate->compilation_cache()->Clear(); | 1464 isolate->compilation_cache()->Clear(); |
| 1462 heap->CollectAllGarbage(Heap::kNoGCFlags); | 1465 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1463 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1466 CHECK_EQ(4, CountOptimizedUserFunctions(ctx[i])); |
| 1464 | 1467 |
| 1465 // Get rid of f3 and f5 in the same way. | 1468 // Get rid of f3 and f5 in the same way. |
| 1466 CompileRun("f3=null"); | 1469 CompileRun("f3=null"); |
| 1467 for (int j = 0; j < 10; j++) { | 1470 for (int j = 0; j < kNumTestCollections; j++) { |
| 1468 CcTest::heap()->CollectGarbage(NEW_SPACE); | 1471 CcTest::heap()->CollectGarbage(NEW_SPACE); |
| 1469 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1472 CHECK_EQ(4, CountOptimizedUserFunctions(ctx[i])); |
| 1470 } | 1473 } |
| 1471 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1474 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1472 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); | 1475 CHECK_EQ(3, CountOptimizedUserFunctions(ctx[i])); |
| 1473 CompileRun("f5=null"); | 1476 CompileRun("f5=null"); |
| 1474 for (int j = 0; j < 10; j++) { | 1477 for (int j = 0; j < kNumTestCollections; j++) { |
| 1475 CcTest::heap()->CollectGarbage(NEW_SPACE); | 1478 CcTest::heap()->CollectGarbage(NEW_SPACE); |
| 1476 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); | 1479 CHECK_EQ(3, CountOptimizedUserFunctions(ctx[i])); |
| 1477 } | 1480 } |
| 1478 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1481 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1479 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); | 1482 CHECK_EQ(2, CountOptimizedUserFunctions(ctx[i])); |
| 1480 | 1483 |
| 1481 ctx[i]->Exit(); | 1484 ctx[i]->Exit(); |
| 1482 } | 1485 } |
| 1483 | 1486 |
| 1484 // Force compilation cache cleanup. | 1487 // Force compilation cache cleanup. |
| 1485 CcTest::heap()->NotifyContextDisposed(); | 1488 CcTest::heap()->NotifyContextDisposed(); |
| 1486 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1489 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1487 | 1490 |
| 1488 // Dispose the native contexts one by one. | 1491 // Dispose the native contexts one by one. |
| 1489 for (int i = 0; i < kNumTestContexts; i++) { | 1492 for (int i = 0; i < kNumTestContexts; i++) { |
| 1490 // TODO(dcarney): is there a better way to do this? | 1493 // TODO(dcarney): is there a better way to do this? |
| 1491 i::Object** unsafe = reinterpret_cast<i::Object**>(*ctx[i]); | 1494 i::Object** unsafe = reinterpret_cast<i::Object**>(*ctx[i]); |
| 1492 *unsafe = CcTest::heap()->undefined_value(); | 1495 *unsafe = CcTest::heap()->undefined_value(); |
| 1493 ctx[i].Clear(); | 1496 ctx[i].Clear(); |
| 1494 | 1497 |
| 1495 // Scavenge treats these references as strong. | 1498 // Scavenge treats these references as strong. |
| 1496 for (int j = 0; j < 10; j++) { | 1499 for (int j = 0; j < kNumTestCollections; j++) { |
| 1497 CcTest::heap()->CollectGarbage(i::NEW_SPACE); | 1500 CcTest::heap()->CollectGarbage(i::NEW_SPACE); |
| 1498 CHECK_EQ(kNumTestContexts - i, CountNativeContexts()); | 1501 CHECK_EQ(kNumTestContexts - i, CountNativeContexts()); |
| 1499 } | 1502 } |
| 1500 | 1503 |
| 1501 // Mark compact handles the weak references. | 1504 // Mark compact handles the weak references. |
| 1502 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1505 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1503 CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts()); | 1506 CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts()); |
| 1504 } | 1507 } |
| 1505 | 1508 |
| 1506 CHECK_EQ(0, CountNativeContexts()); | 1509 CHECK_EQ(0, CountNativeContexts()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1540 if (count == n) isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1543 if (count == n) isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1541 object = Handle<Object>( | 1544 object = Handle<Object>( |
| 1542 Object::cast(JSFunction::cast(*object)->next_function_link()), | 1545 Object::cast(JSFunction::cast(*object)->next_function_link()), |
| 1543 isolate); | 1546 isolate); |
| 1544 } | 1547 } |
| 1545 return count; | 1548 return count; |
| 1546 } | 1549 } |
| 1547 | 1550 |
| 1548 | 1551 |
| 1549 TEST(TestInternalWeakListsTraverseWithGC) { | 1552 TEST(TestInternalWeakListsTraverseWithGC) { |
| 1553 FLAG_allow_natives_syntax = true; |
| 1550 v8::V8::Initialize(); | 1554 v8::V8::Initialize(); |
| 1551 Isolate* isolate = CcTest::i_isolate(); | 1555 Isolate* isolate = CcTest::i_isolate(); |
| 1552 | 1556 |
| 1553 static const int kNumTestContexts = 10; | 1557 // TODO(mstarzinger): Test should be resilient against optimization decisions. |
| 1558 if (i::FLAG_always_opt) return; |
| 1559 if (!isolate->use_crankshaft()) return; |
| 1560 |
| 1561 static const int kNumTestContexts = 5; |
| 1554 | 1562 |
| 1555 HandleScope scope(isolate); | 1563 HandleScope scope(isolate); |
| 1556 v8::Handle<v8::Context> ctx[kNumTestContexts]; | 1564 v8::Handle<v8::Context> ctx[kNumTestContexts]; |
| 1557 | 1565 |
| 1558 CHECK_EQ(0, CountNativeContexts()); | 1566 CHECK_EQ(0, CountNativeContexts()); |
| 1559 | 1567 |
| 1560 // Create an number of contexts and check the length of the weak list both | 1568 // Create an number of contexts and check the length of the weak list both |
| 1561 // with and without GCs while iterating the list. | 1569 // with and without GCs while iterating the list. |
| 1562 for (int i = 0; i < kNumTestContexts; i++) { | 1570 for (int i = 0; i < kNumTestContexts; i++) { |
| 1563 ctx[i] = v8::Context::New(CcTest::isolate()); | 1571 ctx[i] = v8::Context::New(CcTest::isolate()); |
| 1564 CHECK_EQ(i + 1, CountNativeContexts()); | 1572 CHECK_EQ(i + 1, CountNativeContexts()); |
| 1565 CHECK_EQ(i + 1, CountNativeContextsWithGC(isolate, i / 2 + 1)); | 1573 CHECK_EQ(i + 1, CountNativeContextsWithGC(isolate, i / 2 + 1)); |
| 1566 } | 1574 } |
| 1567 | 1575 |
| 1568 bool opt = (FLAG_always_opt && isolate->use_crankshaft()); | |
| 1569 | |
| 1570 // Compile a number of functions the length of the weak list of optimized | 1576 // Compile a number of functions the length of the weak list of optimized |
| 1571 // functions both with and without GCs while iterating the list. | 1577 // functions both with and without GCs while iterating the list. |
| 1572 ctx[0]->Enter(); | 1578 ctx[0]->Enter(); |
| 1573 const char* source = "function f1() { };" | 1579 const char* source = "function f1() { };" |
| 1574 "function f2() { };" | 1580 "function f2() { };" |
| 1575 "function f3() { };" | 1581 "function f3() { };" |
| 1576 "function f4() { };" | 1582 "function f4() { };" |
| 1577 "function f5() { };"; | 1583 "function f5() { };"; |
| 1578 CompileRun(source); | 1584 CompileRun(source); |
| 1579 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[0])); | 1585 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[0])); |
| 1580 CompileRun("f1()"); | 1586 CompileRun("f1(); %OptimizeFunctionOnNextCall(f1); f1()"); |
| 1581 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[0])); | 1587 CHECK_EQ(1, CountOptimizedUserFunctions(ctx[0])); |
| 1582 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); | 1588 CHECK_EQ(1, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); |
| 1583 CompileRun("f2()"); | 1589 CompileRun("f2(); %OptimizeFunctionOnNextCall(f2); f2()"); |
| 1584 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[0])); | 1590 CHECK_EQ(2, CountOptimizedUserFunctions(ctx[0])); |
| 1585 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); | 1591 CHECK_EQ(2, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); |
| 1586 CompileRun("f3()"); | 1592 CompileRun("f3(); %OptimizeFunctionOnNextCall(f3); f3()"); |
| 1587 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[0])); | 1593 CHECK_EQ(3, CountOptimizedUserFunctions(ctx[0])); |
| 1588 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); | 1594 CHECK_EQ(3, CountOptimizedUserFunctionsWithGC(ctx[0], 1)); |
| 1589 CompileRun("f4()"); | 1595 CompileRun("f4(); %OptimizeFunctionOnNextCall(f4); f4()"); |
| 1590 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[0])); | 1596 CHECK_EQ(4, CountOptimizedUserFunctions(ctx[0])); |
| 1591 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 2)); | 1597 CHECK_EQ(4, CountOptimizedUserFunctionsWithGC(ctx[0], 2)); |
| 1592 CompileRun("f5()"); | 1598 CompileRun("f5(); %OptimizeFunctionOnNextCall(f5); f5()"); |
| 1593 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[0])); | 1599 CHECK_EQ(5, CountOptimizedUserFunctions(ctx[0])); |
| 1594 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 4)); | 1600 CHECK_EQ(5, CountOptimizedUserFunctionsWithGC(ctx[0], 4)); |
| 1595 | 1601 |
| 1596 ctx[0]->Exit(); | 1602 ctx[0]->Exit(); |
| 1597 } | 1603 } |
| 1598 | 1604 |
| 1599 | 1605 |
| 1600 TEST(TestSizeOfObjects) { | 1606 TEST(TestSizeOfObjects) { |
| 1601 v8::V8::Initialize(); | 1607 v8::V8::Initialize(); |
| 1602 | 1608 |
| 1603 // Get initial heap size after several full GCs, which will stabilize | 1609 // Get initial heap size after several full GCs, which will stabilize |
| 1604 // the heap size and return with sweeping finished completely. | 1610 // the heap size and return with sweeping finished completely. |
| (...skipping 2442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4047 return result; | 4053 return result; |
| 4048 } | 4054 } |
| 4049 | 4055 |
| 4050 | 4056 |
| 4051 TEST(NextCodeLinkIsWeak) { | 4057 TEST(NextCodeLinkIsWeak) { |
| 4052 i::FLAG_allow_natives_syntax = true; | 4058 i::FLAG_allow_natives_syntax = true; |
| 4053 CcTest::InitializeVM(); | 4059 CcTest::InitializeVM(); |
| 4054 Isolate* isolate = CcTest::i_isolate(); | 4060 Isolate* isolate = CcTest::i_isolate(); |
| 4055 v8::internal::Heap* heap = CcTest::heap(); | 4061 v8::internal::Heap* heap = CcTest::heap(); |
| 4056 | 4062 |
| 4063 // TODO(titzer): Test should be resilient against optimization decisions. |
| 4064 if (i::FLAG_always_opt) return; |
| 4057 if (!isolate->use_crankshaft()) return; | 4065 if (!isolate->use_crankshaft()) return; |
| 4066 |
| 4058 HandleScope outer_scope(heap->isolate()); | 4067 HandleScope outer_scope(heap->isolate()); |
| 4059 Handle<Code> code; | 4068 Handle<Code> code; |
| 4060 heap->CollectAllAvailableGarbage(); | 4069 heap->CollectAllAvailableGarbage(); |
| 4061 int code_chain_length_before, code_chain_length_after; | 4070 int code_chain_length_before, code_chain_length_after; |
| 4062 { | 4071 { |
| 4063 HandleScope scope(heap->isolate()); | 4072 HandleScope scope(heap->isolate()); |
| 4064 Handle<JSFunction> mortal = OptimizeDummyFunction("mortal"); | 4073 Handle<JSFunction> mortal = OptimizeDummyFunction("mortal"); |
| 4065 Handle<JSFunction> immortal = OptimizeDummyFunction("immortal"); | 4074 Handle<JSFunction> immortal = OptimizeDummyFunction("immortal"); |
| 4066 CHECK_EQ(immortal->code()->next_code_link(), mortal->code()); | 4075 CHECK_EQ(immortal->code()->next_code_link(), mortal->code()); |
| 4067 code_chain_length_before = GetCodeChainLength(immortal->code()); | 4076 code_chain_length_before = GetCodeChainLength(immortal->code()); |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4478 #ifdef DEBUG | 4487 #ifdef DEBUG |
| 4479 TEST(PathTracer) { | 4488 TEST(PathTracer) { |
| 4480 CcTest::InitializeVM(); | 4489 CcTest::InitializeVM(); |
| 4481 v8::HandleScope scope(CcTest::isolate()); | 4490 v8::HandleScope scope(CcTest::isolate()); |
| 4482 | 4491 |
| 4483 v8::Local<v8::Value> result = CompileRun("'abc'"); | 4492 v8::Local<v8::Value> result = CompileRun("'abc'"); |
| 4484 Handle<Object> o = v8::Utils::OpenHandle(*result); | 4493 Handle<Object> o = v8::Utils::OpenHandle(*result); |
| 4485 CcTest::i_isolate()->heap()->TracePathToObject(*o); | 4494 CcTest::i_isolate()->heap()->TracePathToObject(*o); |
| 4486 } | 4495 } |
| 4487 #endif // DEBUG | 4496 #endif // DEBUG |
| OLD | NEW |