| Index: src/arm/macro-assembler-arm.cc
|
| ===================================================================
|
| --- src/arm/macro-assembler-arm.cc (revision 10404)
|
| +++ src/arm/macro-assembler-arm.cc (working copy)
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2011 the V8 project authors. All rights reserved.
|
| +// Copyright 2012 the V8 project authors. All rights reserved.
|
| // Redistribution and use in source and binary forms, with or without
|
| // modification, are permitted provided that the following conditions are
|
| // met:
|
| @@ -396,14 +396,14 @@
|
| void MacroAssembler::LoadRoot(Register destination,
|
| Heap::RootListIndex index,
|
| Condition cond) {
|
| - ldr(destination, MemOperand(roots, index << kPointerSizeLog2), cond);
|
| + ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond);
|
| }
|
|
|
|
|
| void MacroAssembler::StoreRoot(Register source,
|
| Heap::RootListIndex index,
|
| Condition cond) {
|
| - str(source, MemOperand(roots, index << kPointerSizeLog2), cond);
|
| + str(source, MemOperand(kRootRegister, index << kPointerSizeLog2), cond);
|
| }
|
|
|
|
|
| @@ -496,13 +496,10 @@
|
| // registers are cp.
|
| ASSERT(!address.is(cp) && !value.is(cp));
|
|
|
| - if (FLAG_debug_code) {
|
| - Label ok;
|
| + if (emit_debug_code()) {
|
| ldr(ip, MemOperand(address));
|
| cmp(ip, value);
|
| - b(eq, &ok);
|
| - stop("Wrong address or value passed to RecordWrite");
|
| - bind(&ok);
|
| + Check(eq, "Wrong address or value passed to RecordWrite");
|
| }
|
|
|
| Label done;
|
| @@ -551,7 +548,7 @@
|
| SaveFPRegsMode fp_mode,
|
| RememberedSetFinalAction and_then) {
|
| Label done;
|
| - if (FLAG_debug_code) {
|
| + if (emit_debug_code()) {
|
| Label ok;
|
| JumpIfNotInNewSpace(object, scratch, &ok);
|
| stop("Remembered set pointer is in new space");
|
| @@ -820,12 +817,12 @@
|
|
|
|
|
| void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
|
| - // Setup the frame structure on the stack.
|
| + // Set up the frame structure on the stack.
|
| ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
|
| ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
|
| ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
|
| Push(lr, fp);
|
| - mov(fp, Operand(sp)); // Setup new frame pointer.
|
| + mov(fp, Operand(sp)); // Set up new frame pointer.
|
| // Reserve room for saved entry sp and code object.
|
| sub(sp, sp, Operand(2 * kPointerSize));
|
| if (emit_debug_code()) {
|
| @@ -1414,6 +1411,35 @@
|
| }
|
|
|
|
|
| +void MacroAssembler::GetNumberHash(Register t0, Register scratch) {
|
| + // First of all we assign the hash seed to scratch.
|
| + LoadRoot(scratch, Heap::kHashSeedRootIndex);
|
| + SmiUntag(scratch);
|
| +
|
| + // Xor original key with a seed.
|
| + eor(t0, t0, Operand(scratch));
|
| +
|
| + // Compute the hash code from the untagged key. This must be kept in sync
|
| + // with ComputeIntegerHash in utils.h.
|
| + //
|
| + // hash = ~hash + (hash << 15);
|
| + mvn(scratch, Operand(t0));
|
| + add(t0, scratch, Operand(t0, LSL, 15));
|
| + // hash = hash ^ (hash >> 12);
|
| + eor(t0, t0, Operand(t0, LSR, 12));
|
| + // hash = hash + (hash << 2);
|
| + add(t0, t0, Operand(t0, LSL, 2));
|
| + // hash = hash ^ (hash >> 4);
|
| + eor(t0, t0, Operand(t0, LSR, 4));
|
| + // hash = hash * 2057;
|
| + mov(scratch, Operand(t0, LSL, 11));
|
| + add(t0, t0, Operand(t0, LSL, 3));
|
| + add(t0, t0, scratch);
|
| + // hash = hash ^ (hash >> 16);
|
| + eor(t0, t0, Operand(t0, LSR, 16));
|
| +}
|
| +
|
| +
|
| void MacroAssembler::LoadFromNumberDictionary(Label* miss,
|
| Register elements,
|
| Register key,
|
| @@ -1443,26 +1469,10 @@
|
| // t2 - used for the index into the dictionary.
|
| Label done;
|
|
|
| - // Compute the hash code from the untagged key. This must be kept in sync
|
| - // with ComputeIntegerHash in utils.h.
|
| - //
|
| - // hash = ~hash + (hash << 15);
|
| - mvn(t1, Operand(t0));
|
| - add(t0, t1, Operand(t0, LSL, 15));
|
| - // hash = hash ^ (hash >> 12);
|
| - eor(t0, t0, Operand(t0, LSR, 12));
|
| - // hash = hash + (hash << 2);
|
| - add(t0, t0, Operand(t0, LSL, 2));
|
| - // hash = hash ^ (hash >> 4);
|
| - eor(t0, t0, Operand(t0, LSR, 4));
|
| - // hash = hash * 2057;
|
| - mov(t1, Operand(2057));
|
| - mul(t0, t0, t1);
|
| - // hash = hash ^ (hash >> 16);
|
| - eor(t0, t0, Operand(t0, LSR, 16));
|
| + GetNumberHash(t0, t1);
|
|
|
| // Compute the capacity mask.
|
| - ldr(t1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset));
|
| + ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset));
|
| mov(t1, Operand(t1, ASR, kSmiTagSize)); // convert smi to int
|
| sub(t1, t1, Operand(1));
|
|
|
| @@ -1473,17 +1483,17 @@
|
| mov(t2, t0);
|
| // Compute the masked index: (hash + i + i * i) & mask.
|
| if (i > 0) {
|
| - add(t2, t2, Operand(NumberDictionary::GetProbeOffset(i)));
|
| + add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i)));
|
| }
|
| and_(t2, t2, Operand(t1));
|
|
|
| // Scale the index by multiplying by the element size.
|
| - ASSERT(NumberDictionary::kEntrySize == 3);
|
| + ASSERT(SeededNumberDictionary::kEntrySize == 3);
|
| add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3
|
|
|
| // Check if the key is identical to the name.
|
| add(t2, elements, Operand(t2, LSL, kPointerSizeLog2));
|
| - ldr(ip, FieldMemOperand(t2, NumberDictionary::kElementsStartOffset));
|
| + ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset));
|
| cmp(key, Operand(ip));
|
| if (i != kProbes - 1) {
|
| b(eq, &done);
|
| @@ -1496,14 +1506,14 @@
|
| // Check that the value is a normal property.
|
| // t2: elements + (index * kPointerSize)
|
| const int kDetailsOffset =
|
| - NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
|
| + SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
|
| ldr(t1, FieldMemOperand(t2, kDetailsOffset));
|
| tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
|
| b(ne, miss);
|
|
|
| // Get the value at the masked, scaled index and return.
|
| const int kValueOffset =
|
| - NumberDictionary::kElementsStartOffset + kPointerSize;
|
| + SeededNumberDictionary::kElementsStartOffset + kPointerSize;
|
| ldr(result, FieldMemOperand(t2, kValueOffset));
|
| }
|
|
|
| @@ -1992,18 +2002,49 @@
|
| }
|
|
|
|
|
| +void MacroAssembler::CompareMap(Register obj,
|
| + Register scratch,
|
| + Handle<Map> map,
|
| + Label* early_success,
|
| + CompareMapMode mode) {
|
| + ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
|
| + cmp(scratch, Operand(map));
|
| + if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
|
| + Map* transitioned_fast_element_map(
|
| + map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL));
|
| + ASSERT(transitioned_fast_element_map == NULL ||
|
| + map->elements_kind() != FAST_ELEMENTS);
|
| + if (transitioned_fast_element_map != NULL) {
|
| + b(eq, early_success);
|
| + cmp(scratch, Operand(Handle<Map>(transitioned_fast_element_map)));
|
| + }
|
| +
|
| + Map* transitioned_double_map(
|
| + map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL));
|
| + ASSERT(transitioned_double_map == NULL ||
|
| + map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
|
| + if (transitioned_double_map != NULL) {
|
| + b(eq, early_success);
|
| + cmp(scratch, Operand(Handle<Map>(transitioned_double_map)));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void MacroAssembler::CheckMap(Register obj,
|
| Register scratch,
|
| Handle<Map> map,
|
| Label* fail,
|
| - SmiCheckType smi_check_type) {
|
| + SmiCheckType smi_check_type,
|
| + CompareMapMode mode) {
|
| if (smi_check_type == DO_SMI_CHECK) {
|
| JumpIfSmi(obj, fail);
|
| }
|
| - ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
|
| - mov(ip, Operand(map));
|
| - cmp(scratch, ip);
|
| +
|
| + Label success;
|
| + CompareMap(obj, scratch, map, &success, mode);
|
| b(ne, fail);
|
| + bind(&success);
|
| }
|
|
|
|
|
| @@ -3460,7 +3501,7 @@
|
| tst(mask_scratch, load_scratch);
|
| b(ne, &done);
|
|
|
| - if (FLAG_debug_code) {
|
| + if (emit_debug_code()) {
|
| // Check for impossible bit pattern.
|
| Label ok;
|
| // LSL may overflow, making the check conservative.
|
|
|