OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 // Get the object to enumerate over. Both SpiderMonkey and JSC | 945 // Get the object to enumerate over. Both SpiderMonkey and JSC |
946 // ignore null and undefined in contrast to the specification; see | 946 // ignore null and undefined in contrast to the specification; see |
947 // ECMA-262 section 12.6.4. | 947 // ECMA-262 section 12.6.4. |
948 VisitForAccumulatorValue(stmt->enumerable()); | 948 VisitForAccumulatorValue(stmt->enumerable()); |
949 __ mov(a0, result_register()); // Result as param to InvokeBuiltin below. | 949 __ mov(a0, result_register()); // Result as param to InvokeBuiltin below. |
950 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 950 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
951 __ Branch(&exit, eq, a0, Operand(at)); | 951 __ Branch(&exit, eq, a0, Operand(at)); |
952 Register null_value = t1; | 952 Register null_value = t1; |
953 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 953 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
954 __ Branch(&exit, eq, a0, Operand(null_value)); | 954 __ Branch(&exit, eq, a0, Operand(null_value)); |
955 | 955 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); |
| 956 __ mov(a0, v0); |
956 // Convert the object to a JS object. | 957 // Convert the object to a JS object. |
957 Label convert, done_convert; | 958 Label convert, done_convert; |
958 __ JumpIfSmi(a0, &convert); | 959 __ JumpIfSmi(a0, &convert); |
959 __ GetObjectType(a0, a1, a1); | 960 __ GetObjectType(a0, a1, a1); |
960 __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); | 961 __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); |
961 __ bind(&convert); | 962 __ bind(&convert); |
962 __ push(a0); | 963 __ push(a0); |
963 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 964 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
964 __ mov(a0, v0); | 965 __ mov(a0, v0); |
965 __ bind(&done_convert); | 966 __ bind(&done_convert); |
966 __ push(a0); | 967 __ push(a0); |
967 | 968 |
968 // Check for proxies. | 969 // Check for proxies. |
969 Label call_runtime; | 970 Label call_runtime; |
970 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 971 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
971 __ GetObjectType(a0, a1, a1); | 972 __ GetObjectType(a0, a1, a1); |
972 __ Branch(&call_runtime, le, a1, Operand(LAST_JS_PROXY_TYPE)); | 973 __ Branch(&call_runtime, le, a1, Operand(LAST_JS_PROXY_TYPE)); |
973 | 974 |
974 // Check cache validity in generated code. This is a fast case for | 975 // Check cache validity in generated code. This is a fast case for |
975 // the JSObject::IsSimpleEnum cache validity checks. If we cannot | 976 // the JSObject::IsSimpleEnum cache validity checks. If we cannot |
976 // guarantee cache validity, call the runtime system to check cache | 977 // guarantee cache validity, call the runtime system to check cache |
977 // validity or get the property names in a fixed array. | 978 // validity or get the property names in a fixed array. |
978 Label next; | 979 __ CheckEnumCache(null_value, &call_runtime); |
979 // Preload a couple of values used in the loop. | |
980 Register empty_fixed_array_value = t2; | |
981 __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); | |
982 Register empty_descriptor_array_value = t3; | |
983 __ LoadRoot(empty_descriptor_array_value, | |
984 Heap::kEmptyDescriptorArrayRootIndex); | |
985 __ mov(a1, a0); | |
986 __ bind(&next); | |
987 | |
988 // Check that there are no elements. Register a1 contains the | |
989 // current JS object we've reached through the prototype chain. | |
990 __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset)); | |
991 __ Branch(&call_runtime, ne, a2, Operand(empty_fixed_array_value)); | |
992 | |
993 // Check that instance descriptors are not empty so that we can | |
994 // check for an enum cache. Leave the map in a2 for the subsequent | |
995 // prototype load. | |
996 __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); | |
997 __ lw(a3, FieldMemOperand(a2, Map::kInstanceDescriptorsOrBitField3Offset)); | |
998 __ JumpIfSmi(a3, &call_runtime); | |
999 | |
1000 // Check that there is an enum cache in the non-empty instance | |
1001 // descriptors (a3). This is the case if the next enumeration | |
1002 // index field does not contain a smi. | |
1003 __ lw(a3, FieldMemOperand(a3, DescriptorArray::kEnumerationIndexOffset)); | |
1004 __ JumpIfSmi(a3, &call_runtime); | |
1005 | |
1006 // For all objects but the receiver, check that the cache is empty. | |
1007 Label check_prototype; | |
1008 __ Branch(&check_prototype, eq, a1, Operand(a0)); | |
1009 __ lw(a3, FieldMemOperand(a3, DescriptorArray::kEnumCacheBridgeCacheOffset)); | |
1010 __ Branch(&call_runtime, ne, a3, Operand(empty_fixed_array_value)); | |
1011 | |
1012 // Load the prototype from the map and loop if non-null. | |
1013 __ bind(&check_prototype); | |
1014 __ lw(a1, FieldMemOperand(a2, Map::kPrototypeOffset)); | |
1015 __ Branch(&next, ne, a1, Operand(null_value)); | |
1016 | 980 |
1017 // The enum cache is valid. Load the map of the object being | 981 // The enum cache is valid. Load the map of the object being |
1018 // iterated over and use the cache for the iteration. | 982 // iterated over and use the cache for the iteration. |
1019 Label use_cache; | 983 Label use_cache; |
1020 __ lw(v0, FieldMemOperand(a0, HeapObject::kMapOffset)); | 984 __ lw(v0, FieldMemOperand(a0, HeapObject::kMapOffset)); |
1021 __ Branch(&use_cache); | 985 __ Branch(&use_cache); |
1022 | 986 |
1023 // Get the set of properties to enumerate. | 987 // Get the set of properties to enumerate. |
1024 __ bind(&call_runtime); | 988 __ bind(&call_runtime); |
1025 __ push(a0); // Duplicate the enumerable object on the stack. | 989 __ push(a0); // Duplicate the enumerable object on the stack. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1057 __ GetObjectType(a2, a3, a3); | 1021 __ GetObjectType(a2, a3, a3); |
1058 __ Branch(&non_proxy, gt, a3, Operand(LAST_JS_PROXY_TYPE)); | 1022 __ Branch(&non_proxy, gt, a3, Operand(LAST_JS_PROXY_TYPE)); |
1059 __ li(a1, Operand(Smi::FromInt(0))); // Zero indicates proxy | 1023 __ li(a1, Operand(Smi::FromInt(0))); // Zero indicates proxy |
1060 __ bind(&non_proxy); | 1024 __ bind(&non_proxy); |
1061 __ Push(a1, v0); // Smi and array | 1025 __ Push(a1, v0); // Smi and array |
1062 __ lw(a1, FieldMemOperand(v0, FixedArray::kLengthOffset)); | 1026 __ lw(a1, FieldMemOperand(v0, FixedArray::kLengthOffset)); |
1063 __ li(a0, Operand(Smi::FromInt(0))); | 1027 __ li(a0, Operand(Smi::FromInt(0))); |
1064 __ Push(a1, a0); // Fixed array length (as smi) and initial index. | 1028 __ Push(a1, a0); // Fixed array length (as smi) and initial index. |
1065 | 1029 |
1066 // Generate code for doing the condition check. | 1030 // Generate code for doing the condition check. |
| 1031 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
1067 __ bind(&loop); | 1032 __ bind(&loop); |
1068 // Load the current count to a0, load the length to a1. | 1033 // Load the current count to a0, load the length to a1. |
1069 __ lw(a0, MemOperand(sp, 0 * kPointerSize)); | 1034 __ lw(a0, MemOperand(sp, 0 * kPointerSize)); |
1070 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | 1035 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); |
1071 __ Branch(loop_statement.break_label(), hs, a0, Operand(a1)); | 1036 __ Branch(loop_statement.break_label(), hs, a0, Operand(a1)); |
1072 | 1037 |
1073 // Get the current entry of the array into register a3. | 1038 // Get the current entry of the array into register a3. |
1074 __ lw(a2, MemOperand(sp, 2 * kPointerSize)); | 1039 __ lw(a2, MemOperand(sp, 2 * kPointerSize)); |
1075 __ Addu(a2, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1040 __ Addu(a2, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
1076 __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize); | 1041 __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize); |
(...skipping 24 matching lines...) Expand all Loading... |
1101 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 1066 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
1102 __ mov(a3, result_register()); | 1067 __ mov(a3, result_register()); |
1103 __ Branch(loop_statement.continue_label(), eq, a3, Operand(zero_reg)); | 1068 __ Branch(loop_statement.continue_label(), eq, a3, Operand(zero_reg)); |
1104 | 1069 |
1105 // Update the 'each' property or variable from the possibly filtered | 1070 // Update the 'each' property or variable from the possibly filtered |
1106 // entry in register a3. | 1071 // entry in register a3. |
1107 __ bind(&update_each); | 1072 __ bind(&update_each); |
1108 __ mov(result_register(), a3); | 1073 __ mov(result_register(), a3); |
1109 // Perform the assignment as if via '='. | 1074 // Perform the assignment as if via '='. |
1110 { EffectContext context(this); | 1075 { EffectContext context(this); |
1111 EmitAssignment(stmt->each(), stmt->AssignmentId()); | 1076 EmitAssignment(stmt->each()); |
1112 } | 1077 } |
1113 | 1078 |
1114 // Generate code for the body of the loop. | 1079 // Generate code for the body of the loop. |
1115 Visit(stmt->body()); | 1080 Visit(stmt->body()); |
1116 | 1081 |
1117 // Generate code for the going to the next element by incrementing | 1082 // Generate code for the going to the next element by incrementing |
1118 // the index (smi) stored on top of the stack. | 1083 // the index (smi) stored on top of the stack. |
1119 __ bind(loop_statement.continue_label()); | 1084 __ bind(loop_statement.continue_label()); |
1120 __ pop(a0); | 1085 __ pop(a0); |
1121 __ Addu(a0, a0, Operand(Smi::FromInt(1))); | 1086 __ Addu(a0, a0, Operand(Smi::FromInt(1))); |
1122 __ push(a0); | 1087 __ push(a0); |
1123 | 1088 |
1124 EmitStackCheck(stmt, &loop); | 1089 EmitStackCheck(stmt, &loop); |
1125 __ Branch(&loop); | 1090 __ Branch(&loop); |
1126 | 1091 |
1127 // Remove the pointers stored on the stack. | 1092 // Remove the pointers stored on the stack. |
1128 __ bind(loop_statement.break_label()); | 1093 __ bind(loop_statement.break_label()); |
1129 __ Drop(5); | 1094 __ Drop(5); |
1130 | 1095 |
1131 // Exit and decrement the loop depth. | 1096 // Exit and decrement the loop depth. |
| 1097 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1132 __ bind(&exit); | 1098 __ bind(&exit); |
1133 decrement_loop_depth(); | 1099 decrement_loop_depth(); |
1134 } | 1100 } |
1135 | 1101 |
1136 | 1102 |
1137 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, | 1103 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
1138 bool pretenure) { | 1104 bool pretenure) { |
1139 // Use the fast case closure allocation code that allocates in new | 1105 // Use the fast case closure allocation code that allocates in new |
1140 // space for nested functions that don't need literals cloning. If | 1106 // space for nested functions that don't need literals cloning. If |
1141 // we're running with the --always-opt or the --prepare-always-opt | 1107 // we're running with the --always-opt or the --prepare-always-opt |
(...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1892 __ mov(a0, result_register()); | 1858 __ mov(a0, result_register()); |
1893 __ pop(a1); | 1859 __ pop(a1); |
1894 BinaryOpStub stub(op, mode); | 1860 BinaryOpStub stub(op, mode); |
1895 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 1861 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
1896 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1862 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
1897 patch_site.EmitPatchInfo(); | 1863 patch_site.EmitPatchInfo(); |
1898 context()->Plug(v0); | 1864 context()->Plug(v0); |
1899 } | 1865 } |
1900 | 1866 |
1901 | 1867 |
1902 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1868 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
1903 // Invalid left-hand sides are rewritten to have a 'throw | 1869 // Invalid left-hand sides are rewritten to have a 'throw |
1904 // ReferenceError' on the left-hand side. | 1870 // ReferenceError' on the left-hand side. |
1905 if (!expr->IsValidLeftHandSide()) { | 1871 if (!expr->IsValidLeftHandSide()) { |
1906 VisitForEffect(expr); | 1872 VisitForEffect(expr); |
1907 return; | 1873 return; |
1908 } | 1874 } |
1909 | 1875 |
1910 // Left-hand side can only be a property, a global or a (parameter or local) | 1876 // Left-hand side can only be a property, a global or a (parameter or local) |
1911 // slot. | 1877 // slot. |
1912 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1878 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1944 __ mov(a1, result_register()); | 1910 __ mov(a1, result_register()); |
1945 __ pop(a2); | 1911 __ pop(a2); |
1946 __ pop(a0); // Restore value. | 1912 __ pop(a0); // Restore value. |
1947 Handle<Code> ic = is_classic_mode() | 1913 Handle<Code> ic = is_classic_mode() |
1948 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 1914 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
1949 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 1915 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
1950 __ Call(ic); | 1916 __ Call(ic); |
1951 break; | 1917 break; |
1952 } | 1918 } |
1953 } | 1919 } |
1954 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | |
1955 context()->Plug(v0); | 1920 context()->Plug(v0); |
1956 } | 1921 } |
1957 | 1922 |
1958 | 1923 |
1959 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1924 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1960 Token::Value op) { | 1925 Token::Value op) { |
1961 if (var->IsUnallocated()) { | 1926 if (var->IsUnallocated()) { |
1962 // Global var, const, or let. | 1927 // Global var, const, or let. |
1963 __ mov(a0, result_register()); | 1928 __ mov(a0, result_register()); |
1964 __ li(a2, Operand(var->name())); | 1929 __ li(a2, Operand(var->name())); |
(...skipping 2500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4465 *context_length = 0; | 4430 *context_length = 0; |
4466 return previous_; | 4431 return previous_; |
4467 } | 4432 } |
4468 | 4433 |
4469 | 4434 |
4470 #undef __ | 4435 #undef __ |
4471 | 4436 |
4472 } } // namespace v8::internal | 4437 } } // namespace v8::internal |
4473 | 4438 |
4474 #endif // V8_TARGET_ARCH_MIPS | 4439 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |