| Index: src/arm/codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/codegen-arm.cc (revision 5316)
|
| +++ src/arm/codegen-arm.cc (working copy)
|
| @@ -1222,21 +1222,26 @@
|
| case Token::SHR:
|
| case Token::SAR: {
|
| ASSERT(!reversed);
|
| - TypeInfo result =
|
| - (op == Token::SAR) ? TypeInfo::Integer32() : TypeInfo::Number();
|
| - if (!reversed) {
|
| - if (op == Token::SHR) {
|
| - if (int_value >= 2) {
|
| - result = TypeInfo::Smi();
|
| - } else if (int_value >= 1) {
|
| - result = TypeInfo::Integer32();
|
| - }
|
| + int shift_amount = int_value & 0x1f;
|
| + TypeInfo result = TypeInfo::Number();
|
| +
|
| + if (op == Token::SHR) {
|
| + if (shift_amount > 1) {
|
| + result = TypeInfo::Smi();
|
| + } else if (shift_amount > 0) {
|
| + result = TypeInfo::Integer32();
|
| + }
|
| + } else if (op == Token::SAR) {
|
| + if (shift_amount > 0) {
|
| + result = TypeInfo::Smi();
|
| } else {
|
| - if (int_value >= 1) {
|
| - result = TypeInfo::Smi();
|
| - }
|
| + result = TypeInfo::Integer32();
|
| }
|
| + } else {
|
| + ASSERT(op == Token::SHL);
|
| + result = TypeInfo::Integer32();
|
| }
|
| +
|
| Register scratch = VirtualFrame::scratch0();
|
| Register scratch2 = VirtualFrame::scratch1();
|
| int shift_value = int_value & 0x1f; // least significant 5 bits
|
| @@ -1556,7 +1561,8 @@
|
| __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
|
| __ b(ne, &build_args);
|
| Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
|
| - __ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeOffset));
|
| + __ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
|
| + __ sub(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
|
| __ cmp(r1, Operand(apply_code));
|
| __ b(ne, &build_args);
|
|
|
| @@ -5264,6 +5270,67 @@
|
| }
|
|
|
|
|
| +void CodeGenerator::GenerateRegExpCloneResult(ZoneList<Expression*>* args) {
|
| + ASSERT_EQ(1, args->length());
|
| +
|
| + Load(args->at(0));
|
| + frame_->PopToR0();
|
| + {
|
| + VirtualFrame::SpilledScope spilled_scope(frame_);
|
| +
|
| + Label done;
|
| + Label call_runtime;
|
| + __ BranchOnSmi(r0, &done);
|
| +
|
| + // Load JSRegExp map into r1. Check that argument object has this map.
|
| + // Arguments to this function should be results of calling RegExp exec,
|
| + // which is either an unmodified JSRegExpResult or null. Anything not having
|
| + // the unmodified JSRegExpResult map is returned unmodified.
|
| + // This also ensures that elements are fast.
|
| +
|
| + __ ldr(r1, ContextOperand(cp, Context::GLOBAL_INDEX));
|
| + __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset));
|
| + __ ldr(r1, ContextOperand(r1, Context::REGEXP_RESULT_MAP_INDEX));
|
| + __ ldr(ip, FieldMemOperand(r0, HeapObject::kMapOffset));
|
| + __ cmp(r1, Operand(ip));
|
| + __ b(ne, &done);
|
| +
|
| + // All set, copy the contents to a new object.
|
| + __ AllocateInNewSpace(JSRegExpResult::kSize,
|
| + r2,
|
| + r3,
|
| + r4,
|
| + &call_runtime,
|
| + NO_ALLOCATION_FLAGS);
|
| + // Store RegExpResult map as map of allocated object.
|
| + ASSERT(JSRegExpResult::kSize == 6 * kPointerSize);
|
| + // Copy all fields (map is already in r1) from (untagged) r0 to r2.
|
| + // Change map of elements array (ends up in r4) to be a FixedCOWArray.
|
| + __ bic(r0, r0, Operand(kHeapObjectTagMask));
|
| + __ ldm(ib, r0, r3.bit() | r4.bit() | r5.bit() | r6.bit() | r7.bit());
|
| + __ stm(ia, r2,
|
| + r1.bit() | r3.bit() | r4.bit() | r5.bit() | r6.bit() | r7.bit());
|
| + ASSERT(!Heap::InNewSpace(Heap::fixed_cow_array_map()));
|
| + ASSERT(JSRegExp::kElementsOffset == 2 * kPointerSize);
|
| + // Check whether elements array is empty fixed array, and otherwise make
|
| + // it copy-on-write (it never should be empty unless someone is messing
|
| + // with the arguments to the runtime function).
|
| + __ LoadRoot(ip, Heap::kEmptyFixedArrayRootIndex);
|
| + __ add(r0, r2, Operand(kHeapObjectTag)); // Tag result and move it to r0.
|
| + __ cmp(r4, ip);
|
| + __ b(eq, &done);
|
| + __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
|
| + __ str(ip, FieldMemOperand(r4, HeapObject::kMapOffset));
|
| + __ b(&done);
|
| + __ bind(&call_runtime);
|
| + __ push(r0);
|
| + __ CallRuntime(Runtime::kRegExpCloneResult, 1);
|
| + __ bind(&done);
|
| + }
|
| + frame_->EmitPush(r0);
|
| +}
|
| +
|
| +
|
| class DeferredSearchCache: public DeferredCode {
|
| public:
|
| DeferredSearchCache(Register dst, Register cache, Register key)
|
| @@ -7028,7 +7095,8 @@
|
| // Initialize the code pointer in the function to be the one
|
| // found in the shared function info object.
|
| __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
|
| - __ str(r3, FieldMemOperand(r0, JSFunction::kCodeOffset));
|
| + __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
|
| + __ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
|
|
|
| // Return result. The argument function info has been popped already.
|
| __ Ret();
|
|
|