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

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 638623002: Keyed stores to super where key is a name. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: All platforms + CR feedback Created 6 years, 2 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 #if V8_TARGET_ARCH_IA32 7 #if V8_TARGET_ARCH_IA32
8 8
9 #include "src/code-factory.h" 9 #include "src/code-factory.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 1796 matching lines...) Expand 10 before | Expand all | Expand 10 after
1807 context()->Plug(eax); 1807 context()->Plug(eax);
1808 } 1808 }
1809 } 1809 }
1810 1810
1811 1811
1812 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1812 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1813 DCHECK(expr->target()->IsValidReferenceExpression()); 1813 DCHECK(expr->target()->IsValidReferenceExpression());
1814 1814
1815 Comment cmnt(masm_, "[ Assignment"); 1815 Comment cmnt(masm_, "[ Assignment");
1816 1816
1817 // Left-hand side can only be a property, a global or a (parameter or local)
1818 // slot.
1819 enum LhsKind {
1820 VARIABLE,
1821 NAMED_PROPERTY,
1822 KEYED_PROPERTY,
1823 NAMED_SUPER_PROPERTY
1824 };
1825 LhsKind assign_type = VARIABLE;
1826 Property* property = expr->target()->AsProperty(); 1817 Property* property = expr->target()->AsProperty();
1827 if (property != NULL) { 1818 LhsKind assign_type = GetAssignType(property);
1828 assign_type = (property->key()->IsPropertyName())
1829 ? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY
1830 : NAMED_PROPERTY)
1831 : KEYED_PROPERTY;
1832 }
1833 1819
1834 // Evaluate LHS expression. 1820 // Evaluate LHS expression.
1835 switch (assign_type) { 1821 switch (assign_type) {
1836 case VARIABLE: 1822 case VARIABLE:
1837 // Nothing to do here. 1823 // Nothing to do here.
1838 break; 1824 break;
1839 case NAMED_SUPER_PROPERTY: 1825 case NAMED_SUPER_PROPERTY:
1840 VisitForStackValue(property->obj()->AsSuperReference()->this_var()); 1826 VisitForStackValue(property->obj()->AsSuperReference()->this_var());
1841 EmitLoadHomeObject(property->obj()->AsSuperReference()); 1827 EmitLoadHomeObject(property->obj()->AsSuperReference());
1842 __ push(result_register()); 1828 __ push(result_register());
1843 if (expr->is_compound()) { 1829 if (expr->is_compound()) {
1844 __ push(MemOperand(esp, kPointerSize)); 1830 __ push(MemOperand(esp, kPointerSize));
1845 __ push(result_register()); 1831 __ push(result_register());
1846 } 1832 }
1847 break; 1833 break;
1848 case NAMED_PROPERTY: 1834 case NAMED_PROPERTY:
1849 if (expr->is_compound()) { 1835 if (expr->is_compound()) {
1850 // We need the receiver both on the stack and in the register. 1836 // We need the receiver both on the stack and in the register.
1851 VisitForStackValue(property->obj()); 1837 VisitForStackValue(property->obj());
1852 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); 1838 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
1853 } else { 1839 } else {
1854 VisitForStackValue(property->obj()); 1840 VisitForStackValue(property->obj());
1855 } 1841 }
1856 break; 1842 break;
1843 case KEYED_SUPER_PROPERTY:
1844 VisitForStackValue(property->obj()->AsSuperReference()->this_var());
1845 EmitLoadHomeObject(property->obj()->AsSuperReference());
1846 __ Push(result_register());
1847 VisitForAccumulatorValue(property->key());
1848 __ Push(result_register());
1849 if (expr->is_compound()) {
1850 __ push(MemOperand(esp, 2 * kPointerSize));
1851 __ push(MemOperand(esp, 2 * kPointerSize));
1852 __ push(result_register());
1853 }
1854 break;
1857 case KEYED_PROPERTY: { 1855 case KEYED_PROPERTY: {
1858 if (expr->is_compound()) { 1856 if (expr->is_compound()) {
1859 VisitForStackValue(property->obj()); 1857 VisitForStackValue(property->obj());
1860 VisitForStackValue(property->key()); 1858 VisitForStackValue(property->key());
1861 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, kPointerSize)); 1859 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, kPointerSize));
1862 __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); 1860 __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0));
1863 } else { 1861 } else {
1864 VisitForStackValue(property->obj()); 1862 VisitForStackValue(property->obj());
1865 VisitForStackValue(property->key()); 1863 VisitForStackValue(property->key());
1866 } 1864 }
(...skipping 12 matching lines...) Expand all
1879 PrepareForBailout(expr->target(), TOS_REG); 1877 PrepareForBailout(expr->target(), TOS_REG);
1880 break; 1878 break;
1881 case NAMED_SUPER_PROPERTY: 1879 case NAMED_SUPER_PROPERTY:
1882 EmitNamedSuperPropertyLoad(property); 1880 EmitNamedSuperPropertyLoad(property);
1883 PrepareForBailoutForId(property->LoadId(), TOS_REG); 1881 PrepareForBailoutForId(property->LoadId(), TOS_REG);
1884 break; 1882 break;
1885 case NAMED_PROPERTY: 1883 case NAMED_PROPERTY:
1886 EmitNamedPropertyLoad(property); 1884 EmitNamedPropertyLoad(property);
1887 PrepareForBailoutForId(property->LoadId(), TOS_REG); 1885 PrepareForBailoutForId(property->LoadId(), TOS_REG);
1888 break; 1886 break;
1887 case KEYED_SUPER_PROPERTY:
1888 EmitKeyedSuperPropertyLoad(property);
1889 PrepareForBailoutForId(property->LoadId(), TOS_REG);
1890 break;
1889 case KEYED_PROPERTY: 1891 case KEYED_PROPERTY:
1890 EmitKeyedPropertyLoad(property); 1892 EmitKeyedPropertyLoad(property);
1891 PrepareForBailoutForId(property->LoadId(), TOS_REG); 1893 PrepareForBailoutForId(property->LoadId(), TOS_REG);
1892 break; 1894 break;
1893 } 1895 }
1894 } 1896 }
1895 1897
1896 Token::Value op = expr->binary_op(); 1898 Token::Value op = expr->binary_op();
1897 __ push(eax); // Left operand goes on the stack. 1899 __ push(eax); // Left operand goes on the stack.
1898 VisitForAccumulatorValue(expr->value()); 1900 VisitForAccumulatorValue(expr->value());
(...skipping 27 matching lines...) Expand all
1926 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1928 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1927 expr->op()); 1929 expr->op());
1928 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 1930 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1929 context()->Plug(eax); 1931 context()->Plug(eax);
1930 break; 1932 break;
1931 case NAMED_PROPERTY: 1933 case NAMED_PROPERTY:
1932 EmitNamedPropertyAssignment(expr); 1934 EmitNamedPropertyAssignment(expr);
1933 break; 1935 break;
1934 case NAMED_SUPER_PROPERTY: 1936 case NAMED_SUPER_PROPERTY:
1935 EmitNamedSuperPropertyStore(property); 1937 EmitNamedSuperPropertyStore(property);
1936 context()->Plug(eax); 1938 context()->Plug(result_register());
1939 break;
1940 case KEYED_SUPER_PROPERTY:
1941 EmitKeyedSuperPropertyStore(property);
1942 context()->Plug(result_register());
1937 break; 1943 break;
1938 case KEYED_PROPERTY: 1944 case KEYED_PROPERTY:
1939 EmitKeyedPropertyAssignment(expr); 1945 EmitKeyedPropertyAssignment(expr);
1940 break; 1946 break;
1941 } 1947 }
1942 } 1948 }
1943 1949
1944 1950
1945 void FullCodeGenerator::VisitYield(Yield* expr) { 1951 void FullCodeGenerator::VisitYield(Yield* expr) {
1946 Comment cmnt(masm_, "[ Yield"); 1952 Comment cmnt(masm_, "[ Yield");
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
2561 2567
2562 2568
2563 void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { 2569 void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
2564 // Assignment to named property of super. 2570 // Assignment to named property of super.
2565 // eax : value 2571 // eax : value
2566 // stack : receiver ('this'), home_object 2572 // stack : receiver ('this'), home_object
2567 DCHECK(prop != NULL); 2573 DCHECK(prop != NULL);
2568 Literal* key = prop->key()->AsLiteral(); 2574 Literal* key = prop->key()->AsLiteral();
2569 DCHECK(key != NULL); 2575 DCHECK(key != NULL);
2570 2576
2577 __ push(Immediate(key->value()));
2571 __ push(eax); 2578 __ push(eax);
2572 __ push(Immediate(key->value()));
2573 __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict 2579 __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
2574 : Runtime::kStoreToSuper_Sloppy), 2580 : Runtime::kStoreToSuper_Sloppy),
2575 4); 2581 4);
2576 } 2582 }
2577 2583
2578 2584
2585 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
2586 // Assignment to named property of super.
2587 // eax : value
2588 // stack : receiver ('this'), home_object, key
2589
2590 __ push(eax);
2591 __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict
2592 : Runtime::kStoreKeyedToSuper_Sloppy),
2593 4);
2594 }
2595
2596
2579 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2597 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2580 // Assignment to a property, using a keyed store IC. 2598 // Assignment to a property, using a keyed store IC.
2581 // eax : value 2599 // eax : value
2582 // esp[0] : key 2600 // esp[0] : key
2583 // esp[kPointerSize] : receiver 2601 // esp[kPointerSize] : receiver
2584 2602
2585 __ pop(StoreDescriptor::NameRegister()); // Key. 2603 __ pop(StoreDescriptor::NameRegister()); // Key.
2586 __ pop(StoreDescriptor::ReceiverRegister()); 2604 __ pop(StoreDescriptor::ReceiverRegister());
2587 DCHECK(StoreDescriptor::ValueRegister().is(eax)); 2605 DCHECK(StoreDescriptor::ValueRegister().is(eax));
2588 // Record source code position before IC call. 2606 // Record source code position before IC call.
(...skipping 1789 matching lines...) Expand 10 before | Expand all | Expand 10 after
4378 } 4396 }
4379 } 4397 }
4380 4398
4381 4399
4382 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 4400 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
4383 DCHECK(expr->expression()->IsValidReferenceExpression()); 4401 DCHECK(expr->expression()->IsValidReferenceExpression());
4384 4402
4385 Comment cmnt(masm_, "[ CountOperation"); 4403 Comment cmnt(masm_, "[ CountOperation");
4386 SetSourcePosition(expr->position()); 4404 SetSourcePosition(expr->position());
4387 4405
4388 // Expression can only be a property, a global or a (parameter or local)
4389 // slot.
4390 enum LhsKind {
4391 VARIABLE,
4392 NAMED_PROPERTY,
4393 KEYED_PROPERTY,
4394 NAMED_SUPER_PROPERTY
4395 };
4396 LhsKind assign_type = VARIABLE;
4397 Property* prop = expr->expression()->AsProperty(); 4406 Property* prop = expr->expression()->AsProperty();
4398 // In case of a property we use the uninitialized expression context 4407 LhsKind assign_type = GetAssignType(prop);
4399 // of the key to detect a named property.
4400 if (prop != NULL) {
4401 assign_type =
4402 (prop->key()->IsPropertyName())
4403 ? (prop->IsSuperAccess() ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
4404 : KEYED_PROPERTY;
4405 }
4406 4408
4407 // Evaluate expression and get value. 4409 // Evaluate expression and get value.
4408 if (assign_type == VARIABLE) { 4410 if (assign_type == VARIABLE) {
4409 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); 4411 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
4410 AccumulatorValueContext context(this); 4412 AccumulatorValueContext context(this);
4411 EmitVariableLoad(expr->expression()->AsVariableProxy()); 4413 EmitVariableLoad(expr->expression()->AsVariableProxy());
4412 } else { 4414 } else {
4413 // Reserve space for result of postfix operation. 4415 // Reserve space for result of postfix operation.
4414 if (expr->is_postfix() && !context()->IsEffect()) { 4416 if (expr->is_postfix() && !context()->IsEffect()) {
4415 __ push(Immediate(Smi::FromInt(0))); 4417 __ push(Immediate(Smi::FromInt(0)));
4416 } 4418 }
4417 if (assign_type == NAMED_PROPERTY) { 4419 switch (assign_type) {
4418 // Put the object both on the stack and in the register. 4420 case NAMED_PROPERTY: {
4419 VisitForStackValue(prop->obj()); 4421 // Put the object both on the stack and in the register.
4420 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); 4422 VisitForStackValue(prop->obj());
4421 EmitNamedPropertyLoad(prop); 4423 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
4422 } else if (assign_type == NAMED_SUPER_PROPERTY) { 4424 EmitNamedPropertyLoad(prop);
4423 VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); 4425 break;
4424 EmitLoadHomeObject(prop->obj()->AsSuperReference()); 4426 }
4425 __ push(result_register()); 4427
4426 __ push(MemOperand(esp, kPointerSize)); 4428 case NAMED_SUPER_PROPERTY: {
4427 __ push(result_register()); 4429 VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
4428 EmitNamedSuperPropertyLoad(prop); 4430 EmitLoadHomeObject(prop->obj()->AsSuperReference());
4429 } else { 4431 __ push(result_register());
4430 VisitForStackValue(prop->obj()); 4432 __ push(MemOperand(esp, kPointerSize));
4431 VisitForStackValue(prop->key()); 4433 __ push(result_register());
4432 __ mov(LoadDescriptor::ReceiverRegister(), 4434 EmitNamedSuperPropertyLoad(prop);
4433 Operand(esp, kPointerSize)); // Object. 4435 break;
4434 __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key. 4436 }
4435 EmitKeyedPropertyLoad(prop); 4437
4438 case KEYED_SUPER_PROPERTY: {
4439 VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
4440 EmitLoadHomeObject(prop->obj()->AsSuperReference());
4441 __ push(result_register());
4442 VisitForAccumulatorValue(prop->key());
4443 __ push(result_register());
4444 __ push(MemOperand(esp, 2 * kPointerSize));
4445 __ push(MemOperand(esp, 2 * kPointerSize));
4446 __ push(result_register());
4447 EmitKeyedSuperPropertyLoad(prop);
4448 break;
4449 }
4450
4451 case KEYED_PROPERTY: {
4452 VisitForStackValue(prop->obj());
4453 VisitForStackValue(prop->key());
4454 __ mov(LoadDescriptor::ReceiverRegister(),
4455 Operand(esp, kPointerSize)); // Object.
4456 __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key.
4457 EmitKeyedPropertyLoad(prop);
4458 break;
4459 }
4460
4461 case VARIABLE:
4462 UNREACHABLE();
4436 } 4463 }
4437 } 4464 }
4438 4465
4439 // We need a second deoptimization point after loading the value 4466 // We need a second deoptimization point after loading the value
4440 // in case evaluating the property load my have a side effect. 4467 // in case evaluating the property load my have a side effect.
4441 if (assign_type == VARIABLE) { 4468 if (assign_type == VARIABLE) {
4442 PrepareForBailout(expr->expression(), TOS_REG); 4469 PrepareForBailout(expr->expression(), TOS_REG);
4443 } else { 4470 } else {
4444 PrepareForBailoutForId(prop->LoadId(), TOS_REG); 4471 PrepareForBailoutForId(prop->LoadId(), TOS_REG);
4445 } 4472 }
(...skipping 17 matching lines...) Expand all
4463 break; 4490 break;
4464 case NAMED_PROPERTY: 4491 case NAMED_PROPERTY:
4465 __ mov(Operand(esp, kPointerSize), eax); 4492 __ mov(Operand(esp, kPointerSize), eax);
4466 break; 4493 break;
4467 case NAMED_SUPER_PROPERTY: 4494 case NAMED_SUPER_PROPERTY:
4468 __ mov(Operand(esp, 2 * kPointerSize), eax); 4495 __ mov(Operand(esp, 2 * kPointerSize), eax);
4469 break; 4496 break;
4470 case KEYED_PROPERTY: 4497 case KEYED_PROPERTY:
4471 __ mov(Operand(esp, 2 * kPointerSize), eax); 4498 __ mov(Operand(esp, 2 * kPointerSize), eax);
4472 break; 4499 break;
4500 case KEYED_SUPER_PROPERTY:
4501 __ mov(Operand(esp, 3 * kPointerSize), eax);
4502 break;
4473 } 4503 }
4474 } 4504 }
4475 } 4505 }
4476 4506
4477 if (expr->op() == Token::INC) { 4507 if (expr->op() == Token::INC) {
4478 __ add(eax, Immediate(Smi::FromInt(1))); 4508 __ add(eax, Immediate(Smi::FromInt(1)));
4479 } else { 4509 } else {
4480 __ sub(eax, Immediate(Smi::FromInt(1))); 4510 __ sub(eax, Immediate(Smi::FromInt(1)));
4481 } 4511 }
4482 __ j(no_overflow, &done, Label::kNear); 4512 __ j(no_overflow, &done, Label::kNear);
(...skipping 21 matching lines...) Expand all
4504 break; 4534 break;
4505 case NAMED_PROPERTY: 4535 case NAMED_PROPERTY:
4506 __ mov(Operand(esp, kPointerSize), eax); 4536 __ mov(Operand(esp, kPointerSize), eax);
4507 break; 4537 break;
4508 case NAMED_SUPER_PROPERTY: 4538 case NAMED_SUPER_PROPERTY:
4509 __ mov(Operand(esp, 2 * kPointerSize), eax); 4539 __ mov(Operand(esp, 2 * kPointerSize), eax);
4510 break; 4540 break;
4511 case KEYED_PROPERTY: 4541 case KEYED_PROPERTY:
4512 __ mov(Operand(esp, 2 * kPointerSize), eax); 4542 __ mov(Operand(esp, 2 * kPointerSize), eax);
4513 break; 4543 break;
4544 case KEYED_SUPER_PROPERTY:
4545 __ mov(Operand(esp, 3 * kPointerSize), eax);
4546 break;
4514 } 4547 }
4515 } 4548 }
4516 } 4549 }
4517 4550
4518 // Record position before stub call. 4551 // Record position before stub call.
4519 SetSourcePosition(expr->position()); 4552 SetSourcePosition(expr->position());
4520 4553
4521 // Call stub for +1/-1. 4554 // Call stub for +1/-1.
4522 __ bind(&stub_call); 4555 __ bind(&stub_call);
4523 __ mov(edx, eax); 4556 __ mov(edx, eax);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
4571 EmitNamedSuperPropertyStore(prop); 4604 EmitNamedSuperPropertyStore(prop);
4572 if (expr->is_postfix()) { 4605 if (expr->is_postfix()) {
4573 if (!context()->IsEffect()) { 4606 if (!context()->IsEffect()) {
4574 context()->PlugTOS(); 4607 context()->PlugTOS();
4575 } 4608 }
4576 } else { 4609 } else {
4577 context()->Plug(eax); 4610 context()->Plug(eax);
4578 } 4611 }
4579 break; 4612 break;
4580 } 4613 }
4614 case KEYED_SUPER_PROPERTY: {
4615 EmitKeyedSuperPropertyStore(prop);
4616 if (expr->is_postfix()) {
4617 if (!context()->IsEffect()) {
4618 context()->PlugTOS();
4619 }
4620 } else {
4621 context()->Plug(eax);
4622 }
4623 break;
4624 }
4581 case KEYED_PROPERTY: { 4625 case KEYED_PROPERTY: {
4582 __ pop(StoreDescriptor::NameRegister()); 4626 __ pop(StoreDescriptor::NameRegister());
4583 __ pop(StoreDescriptor::ReceiverRegister()); 4627 __ pop(StoreDescriptor::ReceiverRegister());
4584 Handle<Code> ic = 4628 Handle<Code> ic =
4585 CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); 4629 CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
4586 CallIC(ic, expr->CountStoreFeedbackId()); 4630 CallIC(ic, expr->CountStoreFeedbackId());
4587 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4631 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4588 if (expr->is_postfix()) { 4632 if (expr->is_postfix()) {
4589 // Result is on the stack 4633 // Result is on the stack
4590 if (!context()->IsEffect()) { 4634 if (!context()->IsEffect()) {
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
5032 DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 5076 DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
5033 Assembler::target_address_at(call_target_address, 5077 Assembler::target_address_at(call_target_address,
5034 unoptimized_code)); 5078 unoptimized_code));
5035 return OSR_AFTER_STACK_CHECK; 5079 return OSR_AFTER_STACK_CHECK;
5036 } 5080 }
5037 5081
5038 5082
5039 } } // namespace v8::internal 5083 } } // namespace v8::internal
5040 5084
5041 #endif // V8_TARGET_ARCH_IA32 5085 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« src/full-codegen.h ('K') | « src/full-codegen.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698