| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |