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

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

Issue 6301: Document (and assert) some of the safe-but-brittle implicit assumptions... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 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
« no previous file with comments | « no previous file | src/codegen-ia32.cc » ('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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 45
46 // A reference is a C++ stack-allocated object that keeps an ECMA 46 // A reference is a C++ stack-allocated object that keeps an ECMA
47 // reference on the execution stack while in scope. For variables 47 // reference on the execution stack while in scope. For variables
48 // the reference is empty, indicating that it isn't necessary to 48 // the reference is empty, indicating that it isn't necessary to
49 // store state on the stack for keeping track of references to those. 49 // store state on the stack for keeping track of references to those.
50 // For properties, we keep either one (named) or two (indexed) values 50 // For properties, we keep either one (named) or two (indexed) values
51 // on the execution stack to represent the reference. 51 // on the execution stack to represent the reference.
52 52
53 class Reference BASE_EMBEDDED { 53 class Reference BASE_EMBEDDED {
54 public: 54 public:
55 enum Type { ILLEGAL = -1, EMPTY = 0, NAMED = 1, KEYED = 2 }; 55 // The values of the types is important, see size().
56 enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
56 Reference(ArmCodeGenerator* cgen, Expression* expression); 57 Reference(ArmCodeGenerator* cgen, Expression* expression);
57 ~Reference(); 58 ~Reference();
58 59
59 Expression* expression() const { return expression_; } 60 Expression* expression() const { return expression_; }
60 Type type() const { return type_; } 61 Type type() const { return type_; }
61 void set_type(Type value) { 62 void set_type(Type value) {
62 ASSERT(type_ == ILLEGAL); 63 ASSERT(type_ == ILLEGAL);
63 type_ = value; 64 type_ = value;
64 } 65 }
65 int size() const { return type_; } 66 // The size of the reference or -1 if the reference is illegal.
67 int size() const { return type_; }
66 68
67 bool is_illegal() const { return type_ == ILLEGAL; } 69 bool is_illegal() const { return type_ == ILLEGAL; }
70 bool is_slot() const { return type_ == SLOT; }
71 bool is_property() const { return type_ == NAMED || type_ == KEYED; }
68 72
69 private: 73 private:
70 ArmCodeGenerator* cgen_; 74 ArmCodeGenerator* cgen_;
71 Expression* expression_; 75 Expression* expression_;
72 Type type_; 76 Type type_;
73 }; 77 };
74 78
75 79
76 // ------------------------------------------------------------------------- 80 // -------------------------------------------------------------------------
77 // Code generation state 81 // Code generation state
(...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 cgen_->UnloadReference(this); 799 cgen_->UnloadReference(this);
796 } 800 }
797 801
798 802
799 void ArmCodeGenerator::LoadReference(Reference* ref) { 803 void ArmCodeGenerator::LoadReference(Reference* ref) {
800 Expression* e = ref->expression(); 804 Expression* e = ref->expression();
801 Property* property = e->AsProperty(); 805 Property* property = e->AsProperty();
802 Variable* var = e->AsVariableProxy()->AsVariable(); 806 Variable* var = e->AsVariableProxy()->AsVariable();
803 807
804 if (property != NULL) { 808 if (property != NULL) {
809 // The expression is either a property or a variable proxy that rewrites
810 // to a property.
805 Load(property->obj()); 811 Load(property->obj());
806 // Used a named reference if the key is a literal symbol. 812 // We use a named reference if the key is a literal symbol, unless it is
807 // We don't use a named reference if they key is a string that can be 813 // a string that can be legally parsed as an integer. This is because
808 // legally parsed as an integer. This is because, otherwise we don't 814 // otherwise we will not get into the slow case code that handles [] on
809 // get into the slow case code that handles [] on String objects. 815 // String objects.
810 Literal* literal = property->key()->AsLiteral(); 816 Literal* literal = property->key()->AsLiteral();
811 uint32_t dummy; 817 uint32_t dummy;
812 if (literal != NULL && literal->handle()->IsSymbol() && 818 if (literal != NULL &&
813 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { 819 literal->handle()->IsSymbol() &&
820 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
814 ref->set_type(Reference::NAMED); 821 ref->set_type(Reference::NAMED);
815 } else { 822 } else {
816 Load(property->key()); 823 Load(property->key());
817 ref->set_type(Reference::KEYED); 824 ref->set_type(Reference::KEYED);
818 } 825 }
819 } else if (var != NULL) { 826 } else if (var != NULL) {
827 // The expression is a variable proxy that does not rewrite to a
828 // property. Global variables are treated as named property references.
820 if (var->is_global()) { 829 if (var->is_global()) {
821 // global variable
822 LoadGlobal(); 830 LoadGlobal();
823 ref->set_type(Reference::NAMED); 831 ref->set_type(Reference::NAMED);
824 } else { 832 } else {
825 // local variable 833 ASSERT(var->slot() != NULL);
826 ref->set_type(Reference::EMPTY); 834 ref->set_type(Reference::SLOT);
827 } 835 }
828 } else { 836 } else {
837 // Anything else is a runtime error.
829 Load(e); 838 Load(e);
830 __ CallRuntime(Runtime::kThrowReferenceError, 1); 839 __ CallRuntime(Runtime::kThrowReferenceError, 1);
831 __ push(r0);
832 } 840 }
833 } 841 }
834 842
835 843
836 void ArmCodeGenerator::UnloadReference(Reference* ref) { 844 void ArmCodeGenerator::UnloadReference(Reference* ref) {
837 int size = ref->size(); 845 int size = ref->size();
838 if (size <= 0) { 846 if (size <= 0) {
839 // Do nothing. No popping is necessary. 847 // Do nothing. No popping is necessary.
840 } else { 848 } else {
841 __ pop(r0); 849 __ pop(r0);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 PrintF("InvokeBuiltinStub (kind %d, argc, %d)\n", 972 PrintF("InvokeBuiltinStub (kind %d, argc, %d)\n",
965 static_cast<int>(kind_), 973 static_cast<int>(kind_),
966 argc_); 974 argc_);
967 } 975 }
968 #endif 976 #endif
969 }; 977 };
970 978
971 979
972 void ArmCodeGenerator::GetReferenceProperty(Expression* key) { 980 void ArmCodeGenerator::GetReferenceProperty(Expression* key) {
973 ASSERT(!ref()->is_illegal()); 981 ASSERT(!ref()->is_illegal());
974 Reference::Type type = ref()->type();
975 982
976 // TODO(1241834): Make sure that this it is safe to ignore the distinction 983 // TODO(1241834): Make sure that this it is safe to ignore the distinction
977 // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance 984 // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance
978 // that reference errors can be thrown below, we must distinguish between 985 // that reference errors can be thrown below, we must distinguish between
979 // the two kinds of loads (typeof expression loads must not throw a 986 // the two kinds of loads (typeof expression loads must not throw a
980 // reference error). 987 // reference error).
981 if (type == Reference::NAMED) { 988 if (ref()->type() == Reference::NAMED) {
982 // Compute the name of the property. 989 // Compute the name of the property.
983 Literal* literal = key->AsLiteral(); 990 Literal* literal = key->AsLiteral();
984 Handle<String> name(String::cast(*literal->handle())); 991 Handle<String> name(String::cast(*literal->handle()));
985 992
986 // Call the appropriate IC code. 993 // Call the appropriate IC code.
987 // Setup the name register. 994 // Setup the name register.
988 __ mov(r2, Operand(name)); 995 __ mov(r2, Operand(name));
989 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 996 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
990 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable(); 997 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();
991 if (var != NULL) { 998 if (var != NULL) {
992 ASSERT(var->is_global()); 999 ASSERT(var->is_global());
993 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 1000 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
994 } else { 1001 } else {
995 __ Call(ic, RelocInfo::CODE_TARGET); 1002 __ Call(ic, RelocInfo::CODE_TARGET);
996 } 1003 }
997 1004
998 } else { 1005 } else {
999 // Access keyed property. 1006 // Access keyed property.
1000 ASSERT(type == Reference::KEYED); 1007 ASSERT(ref()->type() == Reference::KEYED);
1001 1008
1002 // TODO(1224671): Implement inline caching for keyed loads as on ia32. 1009 // TODO(1224671): Implement inline caching for keyed loads as on ia32.
1003 GetPropertyStub stub; 1010 GetPropertyStub stub;
1004 __ CallStub(&stub); 1011 __ CallStub(&stub);
1005 } 1012 }
1006 __ push(r0); 1013 __ push(r0);
1007 } 1014 }
1008 1015
1009 1016
1010 void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) { 1017 void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) {
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 Expression* val = NULL; 1460 Expression* val = NULL;
1454 if (node->mode() == Variable::CONST) { 1461 if (node->mode() == Variable::CONST) {
1455 val = new Literal(Factory::the_hole_value()); 1462 val = new Literal(Factory::the_hole_value());
1456 } else { 1463 } else {
1457 val = node->fun(); // NULL if we don't have a function 1464 val = node->fun(); // NULL if we don't have a function
1458 } 1465 }
1459 1466
1460 if (val != NULL) { 1467 if (val != NULL) {
1461 // Set initial value. 1468 // Set initial value.
1462 Reference target(this, node->proxy()); 1469 Reference target(this, node->proxy());
1470 ASSERT(target.is_slot());
1463 Load(val); 1471 Load(val);
1464 SetValue(&target); 1472 SetValue(&target);
1465 // Get rid of the assigned value (declarations are statements). 1473 // Get rid of the assigned value (declarations are statements). It's
1474 // safe to pop the value lying on top of the reference before unloading
1475 // the reference itself (which preserves the top of stack) because we
1476 // know it is a zero-sized reference.
1466 __ pop(); 1477 __ pop();
1467 } 1478 }
1468 } 1479 }
1469 1480
1470 1481
1471 void ArmCodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { 1482 void ArmCodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
1472 Comment cmnt(masm_, "[ ExpressionStatement"); 1483 Comment cmnt(masm_, "[ ExpressionStatement");
1473 if (FLAG_debug_info) RecordStatementPosition(node); 1484 if (FLAG_debug_info) RecordStatementPosition(node);
1474 Expression* expression = node->expression(); 1485 Expression* expression = node->expression();
1475 expression->MarkAsStatement(); 1486 expression->MarkAsStatement();
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
1937 1948
1938 1949
1939 __ bind(&end_del_check); 1950 __ bind(&end_del_check);
1940 1951
1941 // Store the entry in the 'each' expression and take another spin in the loop. 1952 // Store the entry in the 'each' expression and take another spin in the loop.
1942 // r3: i'th entry of the enum cache (or string there of) 1953 // r3: i'th entry of the enum cache (or string there of)
1943 __ push(r3); // push entry 1954 __ push(r3); // push entry
1944 { Reference each(this, node->each()); 1955 { Reference each(this, node->each());
1945 if (!each.is_illegal()) { 1956 if (!each.is_illegal()) {
1946 if (each.size() > 0) { 1957 if (each.size() > 0) {
1958 // Reference's size is positive.
1947 __ ldr(r0, MemOperand(sp, kPointerSize * each.size())); 1959 __ ldr(r0, MemOperand(sp, kPointerSize * each.size()));
1948 __ push(r0); 1960 __ push(r0);
1949 } 1961 }
1962 // If the reference was to a slot we rely on the convenient property
1963 // that it doesn't matter whether a value (eg, r3 pushed above) is
1964 // right on top of or right underneath a zero-sized reference.
1950 SetValue(&each); 1965 SetValue(&each);
1951 if (each.size() > 0) { 1966 if (each.size() > 0) {
1952 __ pop(r0); // discard the value 1967 // It's safe to pop the value lying on top of the reference before
1968 // unloading the reference itself (which preserves the top of stack,
1969 // ie, now the topmost value of the non-zero sized reference), since
1970 // we will discard the top of stack after unloading the reference
1971 // anyway.
1972 __ pop(r0);
1953 } 1973 }
1954 } 1974 }
1955 } 1975 }
1956 __ pop(); // pop the i'th entry pushed above 1976 // Discard the i'th entry pushed above or else the remainder of the
1977 // reference, whichever is currently on top of the stack.
1978 __ pop();
1957 CheckStack(); // TODO(1222600): ignore if body contains calls. 1979 CheckStack(); // TODO(1222600): ignore if body contains calls.
1958 __ jmp(&loop); 1980 __ jmp(&loop);
1959 1981
1960 // Cleanup. 1982 // Cleanup.
1961 __ bind(&cleanup); 1983 __ bind(&cleanup);
1962 __ bind(node->break_target()); 1984 __ bind(node->break_target());
1963 __ add(sp, sp, Operand(5 * kPointerSize)); 1985 __ add(sp, sp, Operand(5 * kPointerSize));
1964 1986
1965 // Exit. 1987 // Exit.
1966 __ bind(&exit); 1988 __ bind(&exit);
1967 1989
1968 break_stack_height_ -= kForInStackSize; 1990 break_stack_height_ -= kForInStackSize;
1969 } 1991 }
1970 1992
1971 1993
1972 void ArmCodeGenerator::VisitTryCatch(TryCatch* node) { 1994 void ArmCodeGenerator::VisitTryCatch(TryCatch* node) {
1973 Comment cmnt(masm_, "[ TryCatch"); 1995 Comment cmnt(masm_, "[ TryCatch");
1974 1996
1975 Label try_block, exit; 1997 Label try_block, exit;
1976 1998
1977 __ bl(&try_block); 1999 __ bl(&try_block);
1978 2000
1979 // --- Catch block --- 2001 // --- Catch block ---
1980 2002
1981 // Store the caught exception in the catch variable. 2003 // Store the caught exception in the catch variable.
1982 __ push(r0); 2004 __ push(r0);
1983 { Reference ref(this, node->catch_var()); 2005 { Reference ref(this, node->catch_var());
1984 // Load the exception to the top of the stack. 2006 ASSERT(ref.is_slot());
1985 __ ldr(r0, MemOperand(sp, ref.size() * kPointerSize)); 2007 // Here we make use of the convenient property that it doesn't matter
1986 __ push(r0); 2008 // whether a value is immediately on top of or underneath a zero-sized
2009 // reference.
1987 SetValue(&ref); 2010 SetValue(&ref);
1988 __ pop(r0);
1989 } 2011 }
1990 2012
1991 // Remove the exception from the stack. 2013 // Remove the exception from the stack.
1992 __ pop(); 2014 __ pop();
1993 2015
1994 VisitStatements(node->catch_block()->statements()); 2016 VisitStatements(node->catch_block()->statements());
1995 __ b(&exit); 2017 __ b(&exit);
1996 2018
1997 2019
1998 // --- Try block --- 2020 // --- Try block ---
(...skipping 2567 matching lines...) Expand 10 before | Expand all | Expand 10 after
4566 bool is_eval) { 4588 bool is_eval) {
4567 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval); 4589 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval);
4568 if (!code.is_null()) { 4590 if (!code.is_null()) {
4569 Counters::total_compiled_code_size.Increment(code->instruction_size()); 4591 Counters::total_compiled_code_size.Increment(code->instruction_size());
4570 } 4592 }
4571 return code; 4593 return code;
4572 } 4594 }
4573 4595
4574 4596
4575 } } // namespace v8::internal 4597 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698