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

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

Issue 9425045: Support fast case for-in in Crankshaft. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: port to x64&arm, cleanup Created 8 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/arm/lithium-arm.h » ('j') | src/arm/lithium-arm.h » ('J')
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 916 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 // ECMA-262 section 12.6.4. 927 // ECMA-262 section 12.6.4.
928 VisitForAccumulatorValue(stmt->enumerable()); 928 VisitForAccumulatorValue(stmt->enumerable());
929 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 929 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
930 __ cmp(r0, ip); 930 __ cmp(r0, ip);
931 __ b(eq, &exit); 931 __ b(eq, &exit);
932 Register null_value = r5; 932 Register null_value = r5;
933 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 933 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
934 __ cmp(r0, null_value); 934 __ cmp(r0, null_value);
935 __ b(eq, &exit); 935 __ b(eq, &exit);
936 936
937 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
938
937 // Convert the object to a JS object. 939 // Convert the object to a JS object.
938 Label convert, done_convert; 940 Label convert, done_convert;
939 __ JumpIfSmi(r0, &convert); 941 __ JumpIfSmi(r0, &convert);
940 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 942 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
941 __ b(ge, &done_convert); 943 __ b(ge, &done_convert);
942 __ bind(&convert); 944 __ bind(&convert);
943 __ push(r0); 945 __ push(r0);
944 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 946 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
945 __ bind(&done_convert); 947 __ bind(&done_convert);
946 __ push(r0); 948 __ push(r0);
947 949
948 // Check for proxies. 950 // Check for proxies.
949 Label call_runtime; 951 Label call_runtime;
950 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 952 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
951 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); 953 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE);
952 __ b(le, &call_runtime); 954 __ b(le, &call_runtime);
953 955
954 // Check cache validity in generated code. This is a fast case for 956 // Check cache validity in generated code. This is a fast case for
955 // the JSObject::IsSimpleEnum cache validity checks. If we cannot 957 // the JSObject::IsSimpleEnum cache validity checks. If we cannot
956 // guarantee cache validity, call the runtime system to check cache 958 // guarantee cache validity, call the runtime system to check cache
957 // validity or get the property names in a fixed array. 959 // validity or get the property names in a fixed array.
958 Label next; 960 __ CheckEnumCache(null_value, &call_runtime);
959 // Preload a couple of values used in the loop.
960 Register empty_fixed_array_value = r6;
961 __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
962 Register empty_descriptor_array_value = r7;
963 __ LoadRoot(empty_descriptor_array_value,
964 Heap::kEmptyDescriptorArrayRootIndex);
965 __ mov(r1, r0);
966 __ bind(&next);
967
968 // Check that there are no elements. Register r1 contains the
969 // current JS object we've reached through the prototype chain.
970 __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
971 __ cmp(r2, empty_fixed_array_value);
972 __ b(ne, &call_runtime);
973
974 // Check that instance descriptors are not empty so that we can
975 // check for an enum cache. Leave the map in r2 for the subsequent
976 // prototype load.
977 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
978 __ ldr(r3, FieldMemOperand(r2, Map::kInstanceDescriptorsOrBitField3Offset));
979 __ JumpIfSmi(r3, &call_runtime);
980
981 // Check that there is an enum cache in the non-empty instance
982 // descriptors (r3). This is the case if the next enumeration
983 // index field does not contain a smi.
984 __ ldr(r3, FieldMemOperand(r3, DescriptorArray::kEnumerationIndexOffset));
985 __ JumpIfSmi(r3, &call_runtime);
986
987 // For all objects but the receiver, check that the cache is empty.
988 Label check_prototype;
989 __ cmp(r1, r0);
990 __ b(eq, &check_prototype);
991 __ ldr(r3, FieldMemOperand(r3, DescriptorArray::kEnumCacheBridgeCacheOffset));
992 __ cmp(r3, empty_fixed_array_value);
993 __ b(ne, &call_runtime);
994
995 // Load the prototype from the map and loop if non-null.
996 __ bind(&check_prototype);
997 __ ldr(r1, FieldMemOperand(r2, Map::kPrototypeOffset));
998 __ cmp(r1, null_value);
999 __ b(ne, &next);
1000 961
1001 // The enum cache is valid. Load the map of the object being 962 // The enum cache is valid. Load the map of the object being
1002 // iterated over and use the cache for the iteration. 963 // iterated over and use the cache for the iteration.
1003 Label use_cache; 964 Label use_cache;
1004 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 965 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
1005 __ b(&use_cache); 966 __ b(&use_cache);
1006 967
1007 // Get the set of properties to enumerate. 968 // Get the set of properties to enumerate.
1008 __ bind(&call_runtime); 969 __ bind(&call_runtime);
1009 __ push(r0); // Duplicate the enumerable object on the stack. 970 __ push(r0); // Duplicate the enumerable object on the stack.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); 1003 __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE);
1043 __ b(gt, &non_proxy); 1004 __ b(gt, &non_proxy);
1044 __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy 1005 __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy
1045 __ bind(&non_proxy); 1006 __ bind(&non_proxy);
1046 __ Push(r1, r0); // Smi and array 1007 __ Push(r1, r0); // Smi and array
1047 __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); 1008 __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
1048 __ mov(r0, Operand(Smi::FromInt(0))); 1009 __ mov(r0, Operand(Smi::FromInt(0)));
1049 __ Push(r1, r0); // Fixed array length (as smi) and initial index. 1010 __ Push(r1, r0); // Fixed array length (as smi) and initial index.
1050 1011
1051 // Generate code for doing the condition check. 1012 // Generate code for doing the condition check.
1013 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1052 __ bind(&loop); 1014 __ bind(&loop);
1053 // Load the current count to r0, load the length to r1. 1015 // Load the current count to r0, load the length to r1.
1054 __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); 1016 __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
1055 __ cmp(r0, r1); // Compare to the array length. 1017 __ cmp(r0, r1); // Compare to the array length.
1056 __ b(hs, loop_statement.break_label()); 1018 __ b(hs, loop_statement.break_label());
1057 1019
1058 // Get the current entry of the array into register r3. 1020 // Get the current entry of the array into register r3.
1059 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); 1021 __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
1060 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 1022 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1061 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1023 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
(...skipping 23 matching lines...) Expand all
1085 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1047 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1086 __ mov(r3, Operand(r0), SetCC); 1048 __ mov(r3, Operand(r0), SetCC);
1087 __ b(eq, loop_statement.continue_label()); 1049 __ b(eq, loop_statement.continue_label());
1088 1050
1089 // Update the 'each' property or variable from the possibly filtered 1051 // Update the 'each' property or variable from the possibly filtered
1090 // entry in register r3. 1052 // entry in register r3.
1091 __ bind(&update_each); 1053 __ bind(&update_each);
1092 __ mov(result_register(), r3); 1054 __ mov(result_register(), r3);
1093 // Perform the assignment as if via '='. 1055 // Perform the assignment as if via '='.
1094 { EffectContext context(this); 1056 { EffectContext context(this);
1095 EmitAssignment(stmt->each(), stmt->AssignmentId()); 1057 EmitAssignment(stmt->each());
1096 } 1058 }
1097 1059
1098 // Generate code for the body of the loop. 1060 // Generate code for the body of the loop.
1099 Visit(stmt->body()); 1061 Visit(stmt->body());
1100 1062
1101 // Generate code for the going to the next element by incrementing 1063 // Generate code for the going to the next element by incrementing
1102 // the index (smi) stored on top of the stack. 1064 // the index (smi) stored on top of the stack.
1103 __ bind(loop_statement.continue_label()); 1065 __ bind(loop_statement.continue_label());
1104 __ pop(r0); 1066 __ pop(r0);
1105 __ add(r0, r0, Operand(Smi::FromInt(1))); 1067 __ add(r0, r0, Operand(Smi::FromInt(1)));
1106 __ push(r0); 1068 __ push(r0);
1107 1069
1108 EmitStackCheck(stmt, &loop); 1070 EmitStackCheck(stmt, &loop);
1109 __ b(&loop); 1071 __ b(&loop);
1110 1072
1111 // Remove the pointers stored on the stack. 1073 // Remove the pointers stored on the stack.
1112 __ bind(loop_statement.break_label()); 1074 __ bind(loop_statement.break_label());
1113 __ Drop(5); 1075 __ Drop(5);
1114 1076
1115 // Exit and decrement the loop depth. 1077 // Exit and decrement the loop depth.
1078 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1116 __ bind(&exit); 1079 __ bind(&exit);
1117 decrement_loop_depth(); 1080 decrement_loop_depth();
1118 } 1081 }
1119 1082
1120 1083
1121 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 1084 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
1122 bool pretenure) { 1085 bool pretenure) {
1123 // Use the fast case closure allocation code that allocates in new 1086 // Use the fast case closure allocation code that allocates in new
1124 // space for nested functions that don't need literals cloning. If 1087 // space for nested functions that don't need literals cloning. If
1125 // we're running with the --always-opt or the --prepare-always-opt 1088 // we're running with the --always-opt or the --prepare-always-opt
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after
1867 OverwriteMode mode) { 1830 OverwriteMode mode) {
1868 __ pop(r1); 1831 __ pop(r1);
1869 BinaryOpStub stub(op, mode); 1832 BinaryOpStub stub(op, mode);
1870 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 1833 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
1871 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); 1834 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1872 patch_site.EmitPatchInfo(); 1835 patch_site.EmitPatchInfo();
1873 context()->Plug(r0); 1836 context()->Plug(r0);
1874 } 1837 }
1875 1838
1876 1839
1877 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { 1840 void FullCodeGenerator::EmitAssignment(Expression* expr) {
1878 // Invalid left-hand sides are rewritten to have a 'throw 1841 // Invalid left-hand sides are rewritten to have a 'throw
1879 // ReferenceError' on the left-hand side. 1842 // ReferenceError' on the left-hand side.
1880 if (!expr->IsValidLeftHandSide()) { 1843 if (!expr->IsValidLeftHandSide()) {
1881 VisitForEffect(expr); 1844 VisitForEffect(expr);
1882 return; 1845 return;
1883 } 1846 }
1884 1847
1885 // Left-hand side can only be a property, a global or a (parameter or local) 1848 // Left-hand side can only be a property, a global or a (parameter or local)
1886 // slot. 1849 // slot.
1887 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1850 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1919 __ mov(r1, r0); 1882 __ mov(r1, r0);
1920 __ pop(r2); 1883 __ pop(r2);
1921 __ pop(r0); // Restore value. 1884 __ pop(r0); // Restore value.
1922 Handle<Code> ic = is_classic_mode() 1885 Handle<Code> ic = is_classic_mode()
1923 ? isolate()->builtins()->KeyedStoreIC_Initialize() 1886 ? isolate()->builtins()->KeyedStoreIC_Initialize()
1924 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 1887 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
1925 __ Call(ic); 1888 __ Call(ic);
1926 break; 1889 break;
1927 } 1890 }
1928 } 1891 }
1929 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1930 context()->Plug(r0); 1892 context()->Plug(r0);
1931 } 1893 }
1932 1894
1933 1895
1934 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1896 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1935 Token::Value op) { 1897 Token::Value op) {
1936 if (var->IsUnallocated()) { 1898 if (var->IsUnallocated()) {
1937 // Global var, const, or let. 1899 // Global var, const, or let.
1938 __ mov(r2, Operand(var->name())); 1900 __ mov(r2, Operand(var->name()));
1939 __ ldr(r1, GlobalObjectOperand()); 1901 __ ldr(r1, GlobalObjectOperand());
(...skipping 2479 matching lines...) Expand 10 before | Expand all | Expand 10 after
4419 *context_length = 0; 4381 *context_length = 0;
4420 return previous_; 4382 return previous_;
4421 } 4383 }
4422 4384
4423 4385
4424 #undef __ 4386 #undef __
4425 4387
4426 } } // namespace v8::internal 4388 } } // namespace v8::internal
4427 4389
4428 #endif // V8_TARGET_ARCH_ARM 4390 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/arm/lithium-arm.h » ('j') | src/arm/lithium-arm.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698