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

Side by Side Diff: src/mips/full-codegen-mips.cc

Issue 9453009: MIPS: Support fast case for-in in Crankshaft. (Closed)
Patch Set: rebased on r10858. Created 8 years, 9 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
« no previous file with comments | « no previous file | src/mips/lithium-codegen-mips.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 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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/mips/lithium-codegen-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698