| Index: src/arm/codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/codegen-arm.cc (revision 5232)
|
| +++ src/arm/codegen-arm.cc (working copy)
|
| @@ -4800,6 +4800,149 @@
|
| }
|
|
|
|
|
| +// Deferred code to check whether the String JavaScript object is safe for using
|
| +// default value of. This code is called after the bit caching this information
|
| +// in the map has been checked with the map for the object in the map_result_
|
| +// register. On return the register map_result_ contains 1 for true and 0 for
|
| +// false.
|
| +class DeferredIsStringWrapperSafeForDefaultValueOf : public DeferredCode {
|
| + public:
|
| + DeferredIsStringWrapperSafeForDefaultValueOf(Register object,
|
| + Register map_result,
|
| + Register scratch1,
|
| + Register scratch2)
|
| + : object_(object),
|
| + map_result_(map_result),
|
| + scratch1_(scratch1),
|
| + scratch2_(scratch2) { }
|
| +
|
| + virtual void Generate() {
|
| + Label false_result;
|
| +
|
| + // Check that map is loaded as expected.
|
| + if (FLAG_debug_code) {
|
| + __ ldr(ip, FieldMemOperand(object_, HeapObject::kMapOffset));
|
| + __ cmp(map_result_, ip);
|
| + __ Assert(eq, "Map not in expected register");
|
| + }
|
| +
|
| + // Check for fast case object. Generate false result for slow case object.
|
| + __ ldr(scratch1_, FieldMemOperand(object_, JSObject::kPropertiesOffset));
|
| + __ ldr(scratch1_, FieldMemOperand(scratch1_, HeapObject::kMapOffset));
|
| + __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
|
| + __ cmp(scratch1_, ip);
|
| + __ b(eq, &false_result);
|
| +
|
| + // Look for valueOf symbol in the descriptor array, and indicate false if
|
| + // found. The type is not checked, so if it is a transition it is a false
|
| + // negative.
|
| + __ ldr(map_result_,
|
| + FieldMemOperand(map_result_, Map::kInstanceDescriptorsOffset));
|
| + __ ldr(scratch2_, FieldMemOperand(map_result_, FixedArray::kLengthOffset));
|
| + // map_result_: descriptor array
|
| + // scratch2_: length of descriptor array
|
| + // Calculate the end of the descriptor array.
|
| + STATIC_ASSERT(kSmiTag == 0);
|
| + STATIC_ASSERT(kSmiTagSize == 1);
|
| + STATIC_ASSERT(kPointerSize == 4);
|
| + __ add(scratch1_,
|
| + map_result_,
|
| + Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| + __ add(scratch1_,
|
| + scratch1_,
|
| + Operand(scratch2_, LSL, kPointerSizeLog2 - kSmiTagSize));
|
| +
|
| + // Calculate location of the first key name.
|
| + __ add(map_result_,
|
| + map_result_,
|
| + Operand(FixedArray::kHeaderSize +
|
| + DescriptorArray::kFirstIndex * kPointerSize));
|
| + // Loop through all the keys in the descriptor array. If one of these is the
|
| + // symbol valueOf the result is false.
|
| + Label entry, loop;
|
| + __ jmp(&entry);
|
| + __ bind(&loop);
|
| + __ ldr(scratch2_, FieldMemOperand(map_result_, 0));
|
| + __ cmp(scratch2_, Operand(Factory::value_of_symbol()));
|
| + __ b(eq, &false_result);
|
| + __ add(map_result_, map_result_, Operand(kPointerSize));
|
| + __ bind(&entry);
|
| + __ cmp(map_result_, Operand(scratch1_));
|
| + __ b(ne, &loop);
|
| +
|
| + // Reload map as register map_result_ was used as temporary above.
|
| + __ ldr(map_result_, FieldMemOperand(object_, HeapObject::kMapOffset));
|
| +
|
| + // If a valueOf property is not found on the object check that it's
|
| + // prototype is the un-modified String prototype. If not result is false.
|
| + __ ldr(scratch1_, FieldMemOperand(map_result_, Map::kPrototypeOffset));
|
| + __ tst(scratch1_, Operand(kSmiTagMask));
|
| + __ b(eq, &false_result);
|
| + __ ldr(scratch1_, FieldMemOperand(scratch1_, HeapObject::kMapOffset));
|
| + __ ldr(scratch2_,
|
| + CodeGenerator::ContextOperand(cp, Context::GLOBAL_INDEX));
|
| + __ ldr(scratch2_,
|
| + FieldMemOperand(scratch2_, GlobalObject::kGlobalContextOffset));
|
| + __ ldr(scratch2_,
|
| + CodeGenerator::ContextOperand(
|
| + scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
|
| + __ cmp(scratch1_, scratch2_);
|
| + __ b(ne, &false_result);
|
| +
|
| + // Set the bit in the map to indicate that it has been checked safe for
|
| + // default valueOf and set true result.
|
| + __ ldr(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset));
|
| + __ orr(scratch1_,
|
| + scratch1_,
|
| + Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
|
| + __ str(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset));
|
| + __ mov(map_result_, Operand(1));
|
| + __ jmp(exit_label());
|
| + __ bind(&false_result);
|
| + // Set false result.
|
| + __ mov(map_result_, Operand(0));
|
| + }
|
| +
|
| + private:
|
| + Register object_;
|
| + Register map_result_;
|
| + Register scratch1_;
|
| + Register scratch2_;
|
| +};
|
| +
|
| +
|
| +void CodeGenerator::GenerateIsStringWrapperSafeForDefaultValueOf(
|
| + ZoneList<Expression*>* args) {
|
| + ASSERT(args->length() == 1);
|
| + Load(args->at(0));
|
| + Register obj = frame_->PopToRegister(); // Pop the string wrapper.
|
| + if (FLAG_debug_code) {
|
| + __ AbortIfSmi(obj);
|
| + }
|
| +
|
| + // Check whether this map has already been checked to be safe for default
|
| + // valueOf.
|
| + Register map_result = VirtualFrame::scratch0();
|
| + __ ldr(map_result, FieldMemOperand(obj, HeapObject::kMapOffset));
|
| + __ ldrb(ip, FieldMemOperand(map_result, Map::kBitField2Offset));
|
| + __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
|
| + true_target()->Branch(ne);
|
| +
|
| + // We need an additional two scratch registers for the deferred code.
|
| + Register scratch1 = VirtualFrame::scratch1();
|
| + // Use r6 without notifying the virtual frame.
|
| + Register scratch2 = r6;
|
| +
|
| + DeferredIsStringWrapperSafeForDefaultValueOf* deferred =
|
| + new DeferredIsStringWrapperSafeForDefaultValueOf(
|
| + obj, map_result, scratch1, scratch2);
|
| + deferred->Branch(eq);
|
| + deferred->BindExit();
|
| + __ tst(map_result, Operand(map_result));
|
| + cc_reg_ = ne;
|
| +}
|
| +
|
| +
|
| void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
|
| // This generates a fast version of:
|
| // (%_ClassOf(arg) === 'Function')
|
|
|