From 2b91f23b58f12c85e3917aa019fe8aa7508697af Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Fri, 31 Aug 2012 09:50:27 +0000 Subject: [PATCH] MIPS: Use a special EnumLength field to indicate number of valid enum cache values. Port r12400 (03ae62de) Original commit message: This is preparatory work for sharing Enum Caches. BUG= TEST= Review URL: https://chromiumcodereview.appspot.com/10914025 Patch from Akos Palfi . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12417 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/full-codegen-mips.cc | 21 ++++++++----- src/mips/lithium-codegen-mips.cc | 16 ++++++++++ src/mips/lithium-mips.cc | 6 ++++ src/mips/lithium-mips.h | 11 +++++++ src/mips/macro-assembler-mips.cc | 65 ++++++++++++++++++---------------------- src/mips/macro-assembler-mips.h | 1 + 6 files changed, 77 insertions(+), 43 deletions(-) diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index d691a12..6a697bc 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -1141,25 +1141,32 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // modification check. Otherwise, we got a fixed array, and we have // to do a slow check. Label fixed_array; - __ mov(a2, v0); - __ lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); + __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); __ LoadRoot(at, Heap::kMetaMapRootIndex); - __ Branch(&fixed_array, ne, a1, Operand(at)); + __ Branch(&fixed_array, ne, a2, Operand(at)); // We got a map in register v0. Get the enumeration cache from it. + Label no_descriptors; __ bind(&use_cache); - __ LoadInstanceDescriptors(v0, a1, a2); - __ lw(a1, FieldMemOperand(a1, DescriptorArray::kEnumCacheOffset)); - __ lw(a2, FieldMemOperand(a1, DescriptorArray::kEnumCacheBridgeCacheOffset)); + + __ EnumLength(a1, v0); + __ Branch(&no_descriptors, eq, a1, Operand(Smi::FromInt(0))); + + __ LoadInstanceDescriptors(v0, a2, t0); + __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheOffset)); + __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheBridgeCacheOffset)); // Set up the four remaining stack slots. __ push(v0); // Map. - __ lw(a1, FieldMemOperand(a2, FixedArray::kLengthOffset)); __ li(a0, Operand(Smi::FromInt(0))); // Push enumeration cache, enumeration cache length (as smi) and zero. __ Push(a2, a1, a0); __ jmp(&loop); + __ bind(&no_descriptors); + __ Drop(1); + __ jmp(&exit); + // We got a fixed array in register v0. Iterate through that. Label non_proxy; __ bind(&fixed_array); diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 50fe4ac..f6be6a1 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -1224,6 +1224,13 @@ void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { } +void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { + Register result = ToRegister(instr->result()); + Register map = ToRegister(instr->InputAt(0)); + __ EnumLength(result, map); +} + + void LCodeGen::DoElementsKind(LElementsKind* instr) { Register result = ToRegister(instr->result()); Register input = ToRegister(instr->InputAt(0)); @@ -5304,12 +5311,21 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { Register map = ToRegister(instr->map()); Register result = ToRegister(instr->result()); Register scratch = ToRegister(instr->scratch()); + Label load_cache, done; + __ EnumLength(result, map); + __ Branch(&load_cache, ne, result, Operand(Smi::FromInt(0))); + __ li(result, Operand(isolate()->factory()->empty_fixed_array())); + __ jmp(&done); + + __ bind(&load_cache); __ LoadInstanceDescriptors(map, result, scratch); __ lw(result, FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); __ lw(result, FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); + + __ bind(&done); } diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index c9a5064..9cc282b 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -1473,6 +1473,12 @@ LInstruction* LChunkBuilder::DoFixedArrayBaseLength( } +LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) { + LOperand* map = UseRegisterAtStart(instr->value()); + return DefineAsRegister(new(zone()) LMapEnumLength(map)); +} + + LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { LOperand* object = UseRegisterAtStart(instr->value()); return DefineAsRegister(new(zone()) LElementsKind(object)); diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h index 8ea8da4..2d35ede 100644 --- a/src/mips/lithium-mips.h +++ b/src/mips/lithium-mips.h @@ -131,6 +131,7 @@ class LCodeGen; V(LoadNamedField) \ V(LoadNamedFieldPolymorphic) \ V(LoadNamedGeneric) \ + V(MapEnumLength) \ V(MathMinMax) \ V(ModI) \ V(MulI) \ @@ -984,6 +985,16 @@ class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> { }; +class LMapEnumLength: public LTemplateInstruction<1, 1, 0> { + public: + explicit LMapEnumLength(LOperand* value) { + inputs_[0] = value; + } + + DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length") +}; + + class LElementsKind: public LTemplateInstruction<1, 1, 0> { public: explicit LElementsKind(LOperand* value) { diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index d99fbdc..7ded494 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -5313,51 +5313,44 @@ void MacroAssembler::LoadInstanceDescriptors(Register map, } +void MacroAssembler::EnumLength(Register dst, Register map) { + STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); + lw(dst, FieldMemOperand(map, Map::kBitField3Offset)); + And(dst, dst, Operand(Smi::FromInt(Map::EnumLengthBits::kMask))); +} + + void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { - Label next; - // Preload a couple of values used in the loop. Register empty_fixed_array_value = t2; LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); - mov(a1, a0); - bind(&next); + Label next, start; + mov(a2, a0); - // Check that there are no elements. Register a1 contains the - // current JS object we've reached through the prototype chain. - lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset)); - Branch(call_runtime, ne, a2, Operand(empty_fixed_array_value)); - - // Check that instance descriptors are not empty so that we can - // check for an enum cache. Leave the map in a2 for the subsequent - // prototype load. - lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); - lw(a3, FieldMemOperand(a2, Map::kTransitionsOrBackPointerOffset)); + // Check if the enum length field is properly initialized, indicating that + // there is an enum cache. + lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); - CheckMap(a3, - t3, - isolate()->factory()->fixed_array_map(), - call_runtime, - DONT_DO_SMI_CHECK); + EnumLength(a3, a1); + Branch(call_runtime, eq, a3, Operand(Smi::FromInt(Map::kInvalidEnumCache))); - LoadRoot(t3, Heap::kEmptyDescriptorArrayRootIndex); - lw(a3, FieldMemOperand(a3, TransitionArray::kDescriptorsOffset)); - Branch(call_runtime, eq, a3, Operand(t3)); + jmp(&start); - // Check that there is an enum cache in the non-empty instance - // descriptors (a3). This is the case if the next enumeration - // index field does not contain a smi. - lw(a3, FieldMemOperand(a3, DescriptorArray::kEnumCacheOffset)); - JumpIfSmi(a3, call_runtime); + bind(&next); + lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); // For all objects but the receiver, check that the cache is empty. - Label check_prototype; - Branch(&check_prototype, eq, a1, Operand(a0)); - lw(a3, FieldMemOperand(a3, DescriptorArray::kEnumCacheBridgeCacheOffset)); - Branch(call_runtime, ne, a3, Operand(empty_fixed_array_value)); - - // Load the prototype from the map and loop if non-null. - bind(&check_prototype); - lw(a1, FieldMemOperand(a2, Map::kPrototypeOffset)); - Branch(&next, ne, a1, Operand(null_value)); + EnumLength(a3, a1); + Branch(call_runtime, ne, a3, Operand(Smi::FromInt(0))); + + bind(&start); + + // Check that there are no elements. Register r2 contains the current JS + // object we've reached through the prototype chain. + lw(a2, FieldMemOperand(a2, JSObject::kElementsOffset)); + Branch(call_runtime, ne, a2, Operand(empty_fixed_array_value)); + + lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); + Branch(&next, ne, a2, Operand(null_value)); } diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index 0efe8aa..2a77d6c 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -1399,6 +1399,7 @@ class MacroAssembler: public Assembler { void LoadInstanceDescriptors(Register map, Register descriptors, Register scratch); + void EnumLength(Register dst, Register map); // Activation support. -- 2.7.4