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 |