Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: test/cctest/interpreter/test-interpreter.cc

Issue 2263253002: [interpreter] Make the binary op with Smi bytecode handlers collect type feedback. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Update. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/execution.h" 7 #include "src/execution.h"
8 #include "src/handles.h" 8 #include "src/handles.h"
9 #include "src/interpreter/bytecode-array-builder.h" 9 #include "src/interpreter/bytecode-array-builder.h"
10 #include "src/interpreter/bytecode-array-iterator.h" 10 #include "src/interpreter/bytecode-array-iterator.h"
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 Register reg(0); 274 Register reg(0);
275 int lhs = lhs_inputs[l]; 275 int lhs = lhs_inputs[l];
276 int rhs = rhs_inputs[r]; 276 int rhs = rhs_inputs[r];
277 builder.LoadLiteral(Smi::FromInt(lhs)) 277 builder.LoadLiteral(Smi::FromInt(lhs))
278 .StoreAccumulatorInRegister(reg) 278 .StoreAccumulatorInRegister(reg)
279 .LoadLiteral(Smi::FromInt(rhs)) 279 .LoadLiteral(Smi::FromInt(rhs))
280 .BinaryOperation(kShiftOperators[o], reg, vector->GetIndex(slot)) 280 .BinaryOperation(kShiftOperators[o], reg, vector->GetIndex(slot))
281 .Return(); 281 .Return();
282 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); 282 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
283 283
284 InterpreterTester tester(isolate, bytecode_array); 284 InterpreterTester tester(isolate, bytecode_array, vector);
285 auto callable = tester.GetCallable<>(); 285 auto callable = tester.GetCallable<>();
286 Handle<Object> return_value = callable().ToHandleChecked(); 286 Handle<Object> return_value = callable().ToHandleChecked();
287 Handle<Object> expected_value = 287 Handle<Object> expected_value =
288 factory->NewNumber(BinaryOpC(kShiftOperators[o], lhs, rhs)); 288 factory->NewNumber(BinaryOpC(kShiftOperators[o], lhs, rhs));
289 CHECK(return_value->SameValue(*expected_value)); 289 CHECK(return_value->SameValue(*expected_value));
290 } 290 }
291 } 291 }
292 } 292 }
293 } 293 }
294 294
(...skipping 19 matching lines...) Expand all
314 int lhs = lhs_inputs[l]; 314 int lhs = lhs_inputs[l];
315 int rhs = rhs_inputs[r]; 315 int rhs = rhs_inputs[r];
316 builder.LoadLiteral(Smi::FromInt(lhs)) 316 builder.LoadLiteral(Smi::FromInt(lhs))
317 .StoreAccumulatorInRegister(reg) 317 .StoreAccumulatorInRegister(reg)
318 .LoadLiteral(Smi::FromInt(rhs)) 318 .LoadLiteral(Smi::FromInt(rhs))
319 .BinaryOperation(kArithmeticOperators[o], reg, 319 .BinaryOperation(kArithmeticOperators[o], reg,
320 vector->GetIndex(slot)) 320 vector->GetIndex(slot))
321 .Return(); 321 .Return();
322 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); 322 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
323 323
324 InterpreterTester tester(isolate, bytecode_array); 324 InterpreterTester tester(isolate, bytecode_array, vector);
325 auto callable = tester.GetCallable<>(); 325 auto callable = tester.GetCallable<>();
326 Handle<Object> return_value = callable().ToHandleChecked(); 326 Handle<Object> return_value = callable().ToHandleChecked();
327 Handle<Object> expected_value = 327 Handle<Object> expected_value =
328 factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs)); 328 factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs));
329 CHECK(return_value->SameValue(*expected_value)); 329 CHECK(return_value->SameValue(*expected_value));
330 } 330 }
331 } 331 }
332 } 332 }
333 } 333 }
334 334
(...skipping 20 matching lines...) Expand all
355 double lhs = lhs_inputs[l]; 355 double lhs = lhs_inputs[l];
356 double rhs = rhs_inputs[r]; 356 double rhs = rhs_inputs[r];
357 builder.LoadLiteral(factory->NewNumber(lhs)) 357 builder.LoadLiteral(factory->NewNumber(lhs))
358 .StoreAccumulatorInRegister(reg) 358 .StoreAccumulatorInRegister(reg)
359 .LoadLiteral(factory->NewNumber(rhs)) 359 .LoadLiteral(factory->NewNumber(rhs))
360 .BinaryOperation(kArithmeticOperators[o], reg, 360 .BinaryOperation(kArithmeticOperators[o], reg,
361 vector->GetIndex(slot)) 361 vector->GetIndex(slot))
362 .Return(); 362 .Return();
363 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); 363 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
364 364
365 InterpreterTester tester(isolate, bytecode_array); 365 InterpreterTester tester(isolate, bytecode_array, vector);
366 auto callable = tester.GetCallable<>(); 366 auto callable = tester.GetCallable<>();
367 Handle<Object> return_value = callable().ToHandleChecked(); 367 Handle<Object> return_value = callable().ToHandleChecked();
368 Handle<Object> expected_value = 368 Handle<Object> expected_value =
369 factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs)); 369 factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs));
370 CHECK(return_value->SameValue(*expected_value)); 370 CHECK(return_value->SameValue(*expected_value));
371 } 371 }
372 } 372 }
373 } 373 }
374 } 374 }
375 375
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 auto callable = tester.GetCallable<>(); 648 auto callable = tester.GetCallable<>();
649 649
650 Handle<Object> return_val = callable().ToHandleChecked(); 650 Handle<Object> return_val = callable().ToHandleChecked();
651 Object* feedback0 = vector->Get(slot0); 651 Object* feedback0 = vector->Get(slot0);
652 CHECK(feedback0->IsSmi()); 652 CHECK(feedback0->IsSmi());
653 CHECK_EQ(test_case.feedback, static_cast<Smi*>(feedback0)->value()); 653 CHECK_EQ(test_case.feedback, static_cast<Smi*>(feedback0)->value());
654 CHECK(Object::Equals(test_case.result, return_val).ToChecked()); 654 CHECK(Object::Equals(test_case.result, return_val).ToChecked());
655 } 655 }
656 } 656 }
657 657
658 TEST(InterpreterBinaryOpSmiTypeFeedback) {
659 HandleAndZoneScope handles;
660 i::Isolate* isolate = handles.main_isolate();
661 i::Zone zone(isolate->allocator());
662
663 struct BinaryOpExpectation {
664 Token::Value op;
665 Handle<Object> arg1;
666 int32_t arg2;
667 Handle<Object> result;
668 int32_t feedback;
669 };
670
671 BinaryOpExpectation const kTestCases[] = {
672 // ADD
673 {Token::Value::ADD, Handle<Smi>(Smi::FromInt(2), isolate), 42,
674 Handle<Smi>(Smi::FromInt(44), isolate),
675 BinaryOperationFeedback::kSignedSmall},
676 {Token::Value::ADD, Handle<Smi>(Smi::FromInt(2), isolate), Smi::kMaxValue,
677 isolate->factory()->NewHeapNumber(Smi::kMaxValue + 2.0),
678 BinaryOperationFeedback::kNumber},
679 {Token::Value::ADD, isolate->factory()->NewHeapNumber(3.1415), 2,
680 isolate->factory()->NewHeapNumber(3.1415 + 2.0),
681 BinaryOperationFeedback::kNumber},
682 {Token::Value::ADD, isolate->factory()->NewStringFromAsciiChecked("2"), 2,
683 isolate->factory()->NewStringFromAsciiChecked("22"),
684 BinaryOperationFeedback::kAny},
685 // SUB
686 {Token::Value::SUB, Handle<Smi>(Smi::FromInt(2), isolate), 42,
687 Handle<Smi>(Smi::FromInt(-40), isolate),
688 BinaryOperationFeedback::kSignedSmall},
689 {Token::Value::SUB, Handle<Smi>(Smi::FromInt(Smi::kMinValue), isolate), 1,
690 isolate->factory()->NewHeapNumber(Smi::kMinValue - 1.0),
691 BinaryOperationFeedback::kNumber},
692 {Token::Value::SUB, isolate->factory()->NewHeapNumber(3.1415), 2,
693 isolate->factory()->NewHeapNumber(3.1415 - 2.0),
694 BinaryOperationFeedback::kNumber},
695 {Token::Value::SUB, isolate->factory()->NewStringFromAsciiChecked("2"), 2,
696 Handle<Smi>(Smi::FromInt(0), isolate), BinaryOperationFeedback::kAny},
697 // BIT_OR
698 {Token::Value::BIT_OR, Handle<Smi>(Smi::FromInt(4), isolate), 1,
699 Handle<Smi>(Smi::FromInt(5), isolate),
700 BinaryOperationFeedback::kSignedSmall},
701 {Token::Value::BIT_OR, isolate->factory()->NewHeapNumber(3.1415), 8,
702 Handle<Smi>(Smi::FromInt(11), isolate),
703 BinaryOperationFeedback::kNumber},
704 {Token::Value::BIT_OR, isolate->factory()->NewStringFromAsciiChecked("2"),
705 1, Handle<Smi>(Smi::FromInt(3), isolate), BinaryOperationFeedback::kAny},
706 // BIT_AND
707 {Token::Value::BIT_AND, Handle<Smi>(Smi::FromInt(3), isolate), 1,
708 Handle<Smi>(Smi::FromInt(1), isolate),
709 BinaryOperationFeedback::kSignedSmall},
710 {Token::Value::BIT_AND, isolate->factory()->NewHeapNumber(3.1415), 2,
711 Handle<Smi>(Smi::FromInt(2), isolate), BinaryOperationFeedback::kNumber},
712 {Token::Value::BIT_AND,
713 isolate->factory()->NewStringFromAsciiChecked("2"), 1,
714 Handle<Smi>(Smi::FromInt(0), isolate), BinaryOperationFeedback::kAny},
715 // SHL
716 {Token::Value::SHL, Handle<Smi>(Smi::FromInt(3), isolate), 1,
717 Handle<Smi>(Smi::FromInt(6), isolate),
718 BinaryOperationFeedback::kSignedSmall},
719 {Token::Value::SHL, isolate->factory()->NewHeapNumber(3.1415), 2,
720 Handle<Smi>(Smi::FromInt(12), isolate),
721 BinaryOperationFeedback::kNumber},
722 {Token::Value::SHL, isolate->factory()->NewStringFromAsciiChecked("2"), 1,
723 Handle<Smi>(Smi::FromInt(4), isolate), BinaryOperationFeedback::kAny},
724 // SAR
725 {Token::Value::SAR, Handle<Smi>(Smi::FromInt(3), isolate), 1,
726 Handle<Smi>(Smi::FromInt(1), isolate),
727 BinaryOperationFeedback::kSignedSmall},
728 {Token::Value::SAR, isolate->factory()->NewHeapNumber(3.1415), 2,
729 Handle<Smi>(Smi::FromInt(0), isolate), BinaryOperationFeedback::kNumber},
730 {Token::Value::SAR, isolate->factory()->NewStringFromAsciiChecked("2"), 1,
731 Handle<Smi>(Smi::FromInt(1), isolate), BinaryOperationFeedback::kAny}};
732
733 for (const BinaryOpExpectation& test_case : kTestCases) {
734 BytecodeArrayBuilder builder(isolate, handles.main_zone(), 1, 0, 1);
735
736 i::FeedbackVectorSpec feedback_spec(&zone);
737 i::FeedbackVectorSlot slot0 = feedback_spec.AddGeneralSlot();
738
739 Handle<i::TypeFeedbackVector> vector =
740 i::NewTypeFeedbackVector(isolate, &feedback_spec);
741
742 Register reg(0);
743 builder.LoadLiteral(test_case.arg1)
744 .StoreAccumulatorInRegister(reg)
745 .LoadLiteral(Smi::FromInt(test_case.arg2))
746 .BinaryOperation(test_case.op, reg, vector->GetIndex(slot0))
747 .Return();
748
749 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
750
751 InterpreterTester tester(isolate, bytecode_array, vector);
752 auto callable = tester.GetCallable<>();
753
754 Handle<Object> return_val = callable().ToHandleChecked();
755 Object* feedback0 = vector->Get(slot0);
756 CHECK(feedback0->IsSmi());
757 CHECK_EQ(test_case.feedback, static_cast<Smi*>(feedback0)->value());
758 CHECK(Object::Equals(test_case.result, return_val).ToChecked());
759 }
760 }
761
658 TEST(InterpreterUnaryOpFeedback) { 762 TEST(InterpreterUnaryOpFeedback) {
659 HandleAndZoneScope handles; 763 HandleAndZoneScope handles;
660 i::Isolate* isolate = handles.main_isolate(); 764 i::Isolate* isolate = handles.main_isolate();
661 i::Zone zone(isolate->allocator()); 765 i::Zone zone(isolate->allocator());
662 766
663 Handle<Smi> smi_one = Handle<Smi>(Smi::FromInt(1), isolate); 767 Handle<Smi> smi_one = Handle<Smi>(Smi::FromInt(1), isolate);
664 Handle<Smi> smi_max = Handle<Smi>(Smi::FromInt(Smi::kMaxValue), isolate); 768 Handle<Smi> smi_max = Handle<Smi>(Smi::FromInt(Smi::kMaxValue), isolate);
665 Handle<Smi> smi_min = Handle<Smi>(Smi::FromInt(Smi::kMinValue), isolate); 769 Handle<Smi> smi_min = Handle<Smi>(Smi::FromInt(Smi::kMinValue), isolate);
666 Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(2.1); 770 Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(2.1);
667 Handle<String> str = isolate->factory()->NewStringFromAsciiChecked("42"); 771 Handle<String> str = isolate->factory()->NewStringFromAsciiChecked("42");
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 .Jump(&label[2]); 1408 .Jump(&label[2]);
1305 SetRegister(builder, reg, 2048, scratch).Bind(&label[1]); 1409 SetRegister(builder, reg, 2048, scratch).Bind(&label[1]);
1306 IncrementRegister(builder, reg, 2, scratch, vector->GetIndex(slot1)) 1410 IncrementRegister(builder, reg, 2, scratch, vector->GetIndex(slot1))
1307 .Jump(&label[0]); 1411 .Jump(&label[0]);
1308 SetRegister(builder, reg, 4096, scratch).Bind(&label[2]); 1412 SetRegister(builder, reg, 4096, scratch).Bind(&label[2]);
1309 IncrementRegister(builder, reg, 4, scratch, vector->GetIndex(slot2)) 1413 IncrementRegister(builder, reg, 4, scratch, vector->GetIndex(slot2))
1310 .LoadAccumulatorWithRegister(reg) 1414 .LoadAccumulatorWithRegister(reg)
1311 .Return(); 1415 .Return();
1312 1416
1313 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); 1417 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
1314 InterpreterTester tester(isolate, bytecode_array); 1418 InterpreterTester tester(isolate, bytecode_array, vector);
1315 auto callable = tester.GetCallable<>(); 1419 auto callable = tester.GetCallable<>();
1316 Handle<Object> return_value = callable().ToHandleChecked(); 1420 Handle<Object> return_value = callable().ToHandleChecked();
1317 CHECK_EQ(Smi::cast(*return_value)->value(), 7); 1421 CHECK_EQ(Smi::cast(*return_value)->value(), 7);
1318 } 1422 }
1319 1423
1320 1424
1321 TEST(InterpreterConditionalJumps) { 1425 TEST(InterpreterConditionalJumps) {
1322 HandleAndZoneScope handles; 1426 HandleAndZoneScope handles;
1323 Isolate* isolate = handles.main_isolate(); 1427 Isolate* isolate = handles.main_isolate();
1324 Zone zone(isolate->allocator()); 1428 Zone zone(isolate->allocator());
(...skipping 29 matching lines...) Expand all
1354 IncrementRegister(builder, reg, 2, scratch, vector->GetIndex(slot3)) 1458 IncrementRegister(builder, reg, 2, scratch, vector->GetIndex(slot3))
1355 .LoadFalse() 1459 .LoadFalse()
1356 .JumpIfTrue(&done1); 1460 .JumpIfTrue(&done1);
1357 IncrementRegister(builder, reg, 4, scratch, vector->GetIndex(slot4)) 1461 IncrementRegister(builder, reg, 4, scratch, vector->GetIndex(slot4))
1358 .LoadAccumulatorWithRegister(reg) 1462 .LoadAccumulatorWithRegister(reg)
1359 .Bind(&done) 1463 .Bind(&done)
1360 .Bind(&done1) 1464 .Bind(&done1)
1361 .Return(); 1465 .Return();
1362 1466
1363 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); 1467 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
1364 InterpreterTester tester(isolate, bytecode_array); 1468 InterpreterTester tester(isolate, bytecode_array, vector);
1365 auto callable = tester.GetCallable<>(); 1469 auto callable = tester.GetCallable<>();
1366 Handle<Object> return_value = callable().ToHandleChecked(); 1470 Handle<Object> return_value = callable().ToHandleChecked();
1367 CHECK_EQ(Smi::cast(*return_value)->value(), 7); 1471 CHECK_EQ(Smi::cast(*return_value)->value(), 7);
1368 } 1472 }
1369 1473
1370 TEST(InterpreterConditionalJumps2) { 1474 TEST(InterpreterConditionalJumps2) {
1371 // TODO(oth): Add tests for all conditional jumps near and far. 1475 // TODO(oth): Add tests for all conditional jumps near and far.
1372 HandleAndZoneScope handles; 1476 HandleAndZoneScope handles;
1373 Isolate* isolate = handles.main_isolate(); 1477 Isolate* isolate = handles.main_isolate();
1374 Zone zone(isolate->allocator()); 1478 Zone zone(isolate->allocator());
(...skipping 29 matching lines...) Expand all
1404 IncrementRegister(builder, reg, 2, scratch, vector->GetIndex(slot3)) 1508 IncrementRegister(builder, reg, 2, scratch, vector->GetIndex(slot3))
1405 .LoadFalse() 1509 .LoadFalse()
1406 .JumpIfTrue(&done1); 1510 .JumpIfTrue(&done1);
1407 IncrementRegister(builder, reg, 4, scratch, vector->GetIndex(slot4)) 1511 IncrementRegister(builder, reg, 4, scratch, vector->GetIndex(slot4))
1408 .LoadAccumulatorWithRegister(reg) 1512 .LoadAccumulatorWithRegister(reg)
1409 .Bind(&done) 1513 .Bind(&done)
1410 .Bind(&done1) 1514 .Bind(&done1)
1411 .Return(); 1515 .Return();
1412 1516
1413 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); 1517 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
1414 InterpreterTester tester(isolate, bytecode_array); 1518 InterpreterTester tester(isolate, bytecode_array, vector);
1415 auto callable = tester.GetCallable<>(); 1519 auto callable = tester.GetCallable<>();
1416 Handle<Object> return_value = callable().ToHandleChecked(); 1520 Handle<Object> return_value = callable().ToHandleChecked();
1417 CHECK_EQ(Smi::cast(*return_value)->value(), 7); 1521 CHECK_EQ(Smi::cast(*return_value)->value(), 7);
1418 } 1522 }
1419 1523
1420 TEST(InterpreterJumpConstantWith16BitOperand) { 1524 TEST(InterpreterJumpConstantWith16BitOperand) {
1421 HandleAndZoneScope handles; 1525 HandleAndZoneScope handles;
1422 Isolate* isolate = handles.main_isolate(); 1526 Isolate* isolate = handles.main_isolate();
1423 BytecodeArrayBuilder builder(isolate, handles.main_zone(), 1, 0, 257); 1527 BytecodeArrayBuilder builder(isolate, handles.main_zone(), 1, 0, 257);
1424 1528
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1462 while (!iterator.done()) { 1566 while (!iterator.done()) {
1463 if (iterator.current_bytecode() == Bytecode::kJumpConstant && 1567 if (iterator.current_bytecode() == Bytecode::kJumpConstant &&
1464 iterator.current_operand_scale() == OperandScale::kDouble) { 1568 iterator.current_operand_scale() == OperandScale::kDouble) {
1465 found_16bit_constant_jump = true; 1569 found_16bit_constant_jump = true;
1466 break; 1570 break;
1467 } 1571 }
1468 iterator.Advance(); 1572 iterator.Advance();
1469 } 1573 }
1470 CHECK(found_16bit_constant_jump); 1574 CHECK(found_16bit_constant_jump);
1471 1575
1472 InterpreterTester tester(isolate, bytecode_array); 1576 InterpreterTester tester(isolate, bytecode_array, vector);
1473 auto callable = tester.GetCallable<>(); 1577 auto callable = tester.GetCallable<>();
1474 Handle<Object> return_value = callable().ToHandleChecked(); 1578 Handle<Object> return_value = callable().ToHandleChecked();
1475 CHECK_EQ(Smi::cast(*return_value)->value(), 256.0 / 2 * (1 + 256)); 1579 CHECK_EQ(Smi::cast(*return_value)->value(), 256.0 / 2 * (1 + 256));
1476 } 1580 }
1477 1581
1478 TEST(InterpreterJumpWith32BitOperand) { 1582 TEST(InterpreterJumpWith32BitOperand) {
1479 HandleAndZoneScope handles; 1583 HandleAndZoneScope handles;
1480 Isolate* isolate = handles.main_isolate(); 1584 Isolate* isolate = handles.main_isolate();
1481 BytecodeArrayBuilder builder(isolate, handles.main_zone(), 1, 0, 1); 1585 BytecodeArrayBuilder builder(isolate, handles.main_zone(), 1, 0, 1);
1482 Register reg(0); 1586 Register reg(0);
(...skipping 3093 matching lines...) Expand 10 before | Expand all | Expand 10 after
4576 auto callable = tester.GetCallable<>(); 4680 auto callable = tester.GetCallable<>();
4577 4681
4578 Handle<i::Object> return_value = callable().ToHandleChecked(); 4682 Handle<i::Object> return_value = callable().ToHandleChecked();
4579 CHECK(return_value->SameValue(*tests[i].second)); 4683 CHECK(return_value->SameValue(*tests[i].second));
4580 } 4684 }
4581 } 4685 }
4582 4686
4583 } // namespace interpreter 4687 } // namespace interpreter
4584 } // namespace internal 4688 } // namespace internal
4585 } // namespace v8 4689 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698