| 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 |