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

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

Issue 1989012: Add complete implementation of full compiler for the ia32 architecture... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 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
« no previous file with comments | « no previous file | src/codegen.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 case Expression::kUninitialized: 390 case Expression::kUninitialized:
391 391
392 case Expression::kEffect: 392 case Expression::kEffect:
393 ASSERT_EQ(materialize_true, materialize_false); 393 ASSERT_EQ(materialize_true, materialize_false);
394 __ bind(materialize_true); 394 __ bind(materialize_true);
395 break; 395 break;
396 396
397 case Expression::kValue: { 397 case Expression::kValue: {
398 Label done; 398 Label done;
399 __ bind(materialize_true); 399 __ bind(materialize_true);
400 __ mov(result_register(), Operand(Factory::true_value())); 400 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
401 __ jmp(&done); 401 __ jmp(&done);
402 __ bind(materialize_false); 402 __ bind(materialize_false);
403 __ mov(result_register(), Operand(Factory::false_value())); 403 __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
404 __ bind(&done); 404 __ bind(&done);
405 switch (location_) { 405 switch (location_) {
406 case kAccumulator: 406 case kAccumulator:
407 break; 407 break;
408 case kStack: 408 case kStack:
409 __ push(result_register()); 409 __ push(result_register());
410 break; 410 break;
411 } 411 }
412 break; 412 break;
413 } 413 }
414 414
415 case Expression::kTest: 415 case Expression::kTest:
416 break; 416 break;
417 417
418 case Expression::kValueTest: 418 case Expression::kValueTest:
419 __ bind(materialize_true); 419 __ bind(materialize_true);
420 __ mov(result_register(), Operand(Factory::true_value())); 420 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
421 switch (location_) { 421 switch (location_) {
422 case kAccumulator: 422 case kAccumulator:
423 break; 423 break;
424 case kStack: 424 case kStack:
425 __ push(result_register()); 425 __ push(result_register());
426 break; 426 break;
427 } 427 }
428 __ jmp(true_label_); 428 __ jmp(true_label_);
429 break; 429 break;
430 430
431 case Expression::kTestValue: 431 case Expression::kTestValue:
432 __ bind(materialize_false); 432 __ bind(materialize_false);
433 __ mov(result_register(), Operand(Factory::false_value())); 433 __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
434 switch (location_) { 434 switch (location_) {
435 case kAccumulator: 435 case kAccumulator:
436 break; 436 break;
437 case kStack: 437 case kStack:
438 __ push(result_register()); 438 __ push(result_register());
439 break; 439 break;
440 } 440 }
441 __ jmp(false_label_); 441 __ jmp(false_label_);
442 break; 442 break;
443 } 443 }
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 // Call the runtime to declare the globals. 654 // Call the runtime to declare the globals.
655 // The context is the first argument. 655 // The context is the first argument.
656 __ mov(r1, Operand(pairs)); 656 __ mov(r1, Operand(pairs));
657 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); 657 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
658 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); 658 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit());
659 __ CallRuntime(Runtime::kDeclareGlobals, 3); 659 __ CallRuntime(Runtime::kDeclareGlobals, 3);
660 // Return value is ignored. 660 // Return value is ignored.
661 } 661 }
662 662
663 663
664 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 664 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
665 Comment cmnt(masm_, "[ FunctionLiteral"); 665 UNREACHABLE();
666 }
666 667
667 // Build the shared function info and instantiate the function based
668 // on it.
669 Handle<SharedFunctionInfo> function_info =
670 Compiler::BuildFunctionInfo(expr, script(), this);
671 if (HasStackOverflow()) return;
672 668
673 // Create a new closure. 669 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
674 __ mov(r0, Operand(function_info)); 670 UNREACHABLE();
675 __ stm(db_w, sp, cp.bit() | r0.bit()); 671 }
676 __ CallRuntime(Runtime::kNewClosure, 2); 672
673
674 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
675 // Use the fast case closure allocation code that allocates in new
676 // space for nested functions that don't need literals cloning.
677 if (scope()->is_function_scope() && info->num_literals() == 0) {
678 FastNewClosureStub stub;
679 __ mov(r0, Operand(info));
680 __ push(r0);
681 __ CallStub(&stub);
682 } else {
683 __ mov(r0, Operand(info));
684 __ stm(db_w, sp, cp.bit() | r0.bit());
685 __ CallRuntime(Runtime::kNewClosure, 2);
686 }
677 Apply(context_, r0); 687 Apply(context_, r0);
678 } 688 }
679 689
680 690
681 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 691 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
682 Comment cmnt(masm_, "[ VariableProxy"); 692 Comment cmnt(masm_, "[ VariableProxy");
683 EmitVariableLoad(expr->var(), context_); 693 EmitVariableLoad(expr->var(), context_);
684 } 694 }
685 695
686 696
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 if (result_saved) { 907 if (result_saved) {
898 ApplyTOS(context_); 908 ApplyTOS(context_);
899 } else { 909 } else {
900 Apply(context_, r0); 910 Apply(context_, r0);
901 } 911 }
902 } 912 }
903 913
904 914
905 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 915 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
906 Comment cmnt(masm_, "[ Assignment"); 916 Comment cmnt(masm_, "[ Assignment");
907 ASSERT(expr->op() != Token::INIT_CONST); 917 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
918 // on the left-hand side.
919 if (!expr->target()->IsValidLeftHandSide()) {
920 VisitForEffect(expr->target());
921 return;
922 }
923
908 // Left-hand side can only be a property, a global or a (parameter or local) 924 // Left-hand side can only be a property, a global or a (parameter or local)
909 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 925 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
910 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 926 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
911 LhsKind assign_type = VARIABLE; 927 LhsKind assign_type = VARIABLE;
912 Property* prop = expr->target()->AsProperty(); 928 Property* prop = expr->target()->AsProperty();
913 if (prop != NULL) { 929 if (prop != NULL) {
914 assign_type = 930 assign_type =
915 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 931 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
916 } 932 }
917 933
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 location_ = saved_location; 993 location_ = saved_location;
978 } 994 }
979 995
980 // Record source position before possible IC call. 996 // Record source position before possible IC call.
981 SetSourcePosition(expr->position()); 997 SetSourcePosition(expr->position());
982 998
983 // Store the value. 999 // Store the value.
984 switch (assign_type) { 1000 switch (assign_type) {
985 case VARIABLE: 1001 case VARIABLE:
986 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1002 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1003 expr->op(),
987 context_); 1004 context_);
988 break; 1005 break;
989 case NAMED_PROPERTY: 1006 case NAMED_PROPERTY:
990 EmitNamedPropertyAssignment(expr); 1007 EmitNamedPropertyAssignment(expr);
991 break; 1008 break;
992 case KEYED_PROPERTY: 1009 case KEYED_PROPERTY:
993 EmitKeyedPropertyAssignment(expr); 1010 EmitKeyedPropertyAssignment(expr);
994 break; 1011 break;
995 } 1012 }
996 } 1013 }
(...skipping 20 matching lines...) Expand all
1017 void FullCodeGenerator::EmitBinaryOp(Token::Value op, 1034 void FullCodeGenerator::EmitBinaryOp(Token::Value op,
1018 Expression::Context context) { 1035 Expression::Context context) {
1019 __ pop(r1); 1036 __ pop(r1);
1020 GenericBinaryOpStub stub(op, NO_OVERWRITE, r1, r0); 1037 GenericBinaryOpStub stub(op, NO_OVERWRITE, r1, r0);
1021 __ CallStub(&stub); 1038 __ CallStub(&stub);
1022 Apply(context, r0); 1039 Apply(context, r0);
1023 } 1040 }
1024 1041
1025 1042
1026 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1043 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1044 Token::Value op,
1027 Expression::Context context) { 1045 Expression::Context context) {
1028 // Three main cases: global variables, lookup slots, and all other 1046 // Left-hand sides that rewrite to explicit property accesses do not reach
1029 // types of slots. Left-hand-side parameters that rewrite to 1047 // here.
1030 // explicit property accesses do not reach here.
1031 ASSERT(var != NULL); 1048 ASSERT(var != NULL);
1032 ASSERT(var->is_global() || var->slot() != NULL); 1049 ASSERT(var->is_global() || var->slot() != NULL);
1033 1050
1034 Slot* slot = var->slot();
1035 if (var->is_global()) { 1051 if (var->is_global()) {
1036 ASSERT(!var->is_this()); 1052 ASSERT(!var->is_this());
1037 // Assignment to a global variable. Use inline caching for the 1053 // Assignment to a global variable. Use inline caching for the
1038 // assignment. Right-hand-side value is passed in r0, variable name in 1054 // assignment. Right-hand-side value is passed in r0, variable name in
1039 // r2, and the global object in r1. 1055 // r2, and the global object in r1.
1040 __ mov(r2, Operand(var->name())); 1056 __ mov(r2, Operand(var->name()));
1041 __ ldr(r1, CodeGenerator::GlobalObject()); 1057 __ ldr(r1, CodeGenerator::GlobalObject());
1042 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1058 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1043 __ Call(ic, RelocInfo::CODE_TARGET); 1059 __ Call(ic, RelocInfo::CODE_TARGET);
1044 1060
1045 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1061 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
1046 __ push(result_register()); // Value. 1062 // Perform the assignment for non-const variables and for initialization
1047 __ mov(r1, Operand(var->name())); 1063 // of const variables. Const assignments are simply skipped.
1048 __ stm(db_w, sp, cp.bit() | r1.bit()); // Context and name. 1064 Label done;
1049 __ CallRuntime(Runtime::kStoreContextSlot, 3);
1050
1051 } else if (var->slot() != NULL) {
1052 Slot* slot = var->slot(); 1065 Slot* slot = var->slot();
1053 switch (slot->type()) { 1066 switch (slot->type()) {
1067 case Slot::PARAMETER:
1054 case Slot::LOCAL: 1068 case Slot::LOCAL:
1055 case Slot::PARAMETER: 1069 if (op == Token::INIT_CONST) {
1070 // Detect const reinitialization by checking for the hole value.
1071 __ ldr(r1, MemOperand(fp, SlotOffset(slot)));
1072 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1073 __ cmp(r1, ip);
1074 __ b(ne, &done);
1075 }
1076 // Perform the assignment.
1056 __ str(result_register(), MemOperand(fp, SlotOffset(slot))); 1077 __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
1057 break; 1078 break;
1058 1079
1059 case Slot::CONTEXT: { 1080 case Slot::CONTEXT: {
1060 MemOperand target = EmitSlotSearch(slot, r1); 1081 MemOperand target = EmitSlotSearch(slot, r1);
1082 if (op == Token::INIT_CONST) {
1083 // Detect const reinitialization by checking for the hole value.
1084 __ ldr(r1, target);
1085 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1086 __ cmp(r1, ip);
1087 __ b(ne, &done);
1088 }
1089 // Perform the assignment and issue the write barrier.
1061 __ str(result_register(), target); 1090 __ str(result_register(), target);
1062
1063 // RecordWrite may destroy all its register arguments. 1091 // RecordWrite may destroy all its register arguments.
1064 __ mov(r3, result_register()); 1092 __ mov(r3, result_register());
1065 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 1093 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
1066
1067 __ mov(r2, Operand(offset)); 1094 __ mov(r2, Operand(offset));
1068 __ RecordWrite(r1, r2, r3); 1095 __ RecordWrite(r1, r2, r3);
1069 break; 1096 break;
1070 } 1097 }
1071 1098
1072 case Slot::LOOKUP: 1099 case Slot::LOOKUP:
1073 UNREACHABLE(); 1100 // Call the runtime for the assignment. The runtime will ignore
1101 // const reinitialization.
1102 __ push(r0); // Value.
1103 __ mov(r0, Operand(slot->var()->name()));
1104 __ Push(cp, r0); // Context and name.
1105 if (op == Token::INIT_CONST) {
1106 // The runtime will ignore const redeclaration.
1107 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1108 } else {
1109 __ CallRuntime(Runtime::kStoreContextSlot, 3);
1110 }
1074 break; 1111 break;
1075 } 1112 }
1113 __ bind(&done);
1114 }
1076 1115
1077 } else {
1078 // Variables rewritten as properties are not treated as variables in
1079 // assignments.
1080 UNREACHABLE();
1081 }
1082 Apply(context, result_register()); 1116 Apply(context, result_register());
1083 } 1117 }
1084 1118
1085 1119
1086 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1120 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1087 // Assignment to a property, using a named store IC. 1121 // Assignment to a property, using a named store IC.
1088 Property* prop = expr->target()->AsProperty(); 1122 Property* prop = expr->target()->AsProperty();
1089 ASSERT(prop != NULL); 1123 ASSERT(prop != NULL);
1090 ASSERT(prop->key()->AsLiteral() != NULL); 1124 ASSERT(prop->key()->AsLiteral() != NULL);
1091 1125
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
1624 __ mov(r1, Operand(Smi::FromInt(count_value))); 1658 __ mov(r1, Operand(Smi::FromInt(count_value)));
1625 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); 1659 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0);
1626 __ CallStub(&stub); 1660 __ CallStub(&stub);
1627 __ bind(&done); 1661 __ bind(&done);
1628 1662
1629 // Store the value returned in r0. 1663 // Store the value returned in r0.
1630 switch (assign_type) { 1664 switch (assign_type) {
1631 case VARIABLE: 1665 case VARIABLE:
1632 if (expr->is_postfix()) { 1666 if (expr->is_postfix()) {
1633 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1667 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1668 Token::ASSIGN,
1634 Expression::kEffect); 1669 Expression::kEffect);
1635 // For all contexts except kEffect: We have the result on 1670 // For all contexts except kEffect: We have the result on
1636 // top of the stack. 1671 // top of the stack.
1637 if (context_ != Expression::kEffect) { 1672 if (context_ != Expression::kEffect) {
1638 ApplyTOS(context_); 1673 ApplyTOS(context_);
1639 } 1674 }
1640 } else { 1675 } else {
1641 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1676 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1677 Token::ASSIGN,
1642 context_); 1678 context_);
1643 } 1679 }
1644 break; 1680 break;
1645 case NAMED_PROPERTY: { 1681 case NAMED_PROPERTY: {
1646 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 1682 __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
1647 __ pop(r1); 1683 __ pop(r1);
1648 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1684 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1649 __ Call(ic, RelocInfo::CODE_TARGET); 1685 __ Call(ic, RelocInfo::CODE_TARGET);
1650 if (expr->is_postfix()) { 1686 if (expr->is_postfix()) {
1651 if (context_ != Expression::kEffect) { 1687 if (context_ != Expression::kEffect) {
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1870 __ pop(result_register()); 1906 __ pop(result_register());
1871 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 1907 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
1872 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 1908 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value.
1873 __ add(pc, r1, Operand(masm_->CodeObject())); 1909 __ add(pc, r1, Operand(masm_->CodeObject()));
1874 } 1910 }
1875 1911
1876 1912
1877 #undef __ 1913 #undef __
1878 1914
1879 } } // namespace v8::internal 1915 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/codegen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698