Improved string hash-code distribution by excluding bit-field bits from the hash-code.
Changed string search algorithm used in indexOf from KMP to Boyer-Moore.
Improved the generated code for the instanceof operator.
Improved performance of slow-case string equality checks by specializing the code based on the string representation.
Improve the handling of out-of-memory situations (issue 70).
Improved performance of strict equality checks.
Improved profiler output to make it easier to see anonymous functions.
Improved performance of slow-case keyed loads.
Improved property access performance by allocating a number of properties in the front object.
Changed the toString behavior on the built-in object constructors to print [native code] instead of the actual source. Some web applications do not like constructors with complex toString results.
git-svn-id: http://v8.googlecode.com/svn/trunk@511 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/stub-cache-ia32.cc b/src/stub-cache-ia32.cc
index a7d8a7b..01526da 100644
--- a/src/stub-cache-ia32.cc
+++ b/src/stub-cache-ia32.cc
@@ -99,8 +99,8 @@
__ j(zero, &miss, not_taken);
// Get the map of the receiver and compute the hash.
- __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
- __ add(scratch, FieldOperand(name, String::kLengthOffset));
+ __ mov(scratch, FieldOperand(name, String::kLengthOffset));
+ __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
__ xor_(scratch, flags);
__ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
@@ -232,52 +232,30 @@
Register scratch1,
Register scratch2,
Label* miss_label) {
- // Check that the receiver isn't a smi.
- __ test(receiver, Immediate(kSmiTagMask));
- __ j(zero, miss_label, not_taken);
-
- // Check that the receiver is a function.
- __ mov(scratch1, FieldOperand(receiver, HeapObject::kMapOffset));
- __ movzx_b(scratch2, FieldOperand(scratch1, Map::kInstanceTypeOffset));
- __ cmp(scratch2, JS_FUNCTION_TYPE);
- __ j(not_equal, miss_label, not_taken);
-
- // Make sure that the function has an instance prototype.
- Label non_instance;
- __ movzx_b(scratch2, FieldOperand(scratch1, Map::kBitFieldOffset));
- __ test(scratch2, Immediate(1 << Map::kHasNonInstancePrototype));
- __ j(not_zero, &non_instance, not_taken);
-
- // Get the prototype or initial map from the function.
- __ mov(scratch1,
- FieldOperand(receiver, JSFunction::kPrototypeOrInitialMapOffset));
-
- // If the prototype or initial map is the hole, don't return it and
- // simply miss the cache instead. This will allow us to allocate a
- // prototype object on-demand in the runtime system.
- __ cmp(Operand(scratch1), Immediate(Factory::the_hole_value()));
- __ j(equal, miss_label, not_taken);
+ __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
__ mov(eax, Operand(scratch1));
-
- // If the function does not have an initial map, we're done.
- Label done;
- __ mov(scratch1, FieldOperand(eax, HeapObject::kMapOffset));
- __ movzx_b(scratch2, FieldOperand(scratch1, Map::kInstanceTypeOffset));
- __ cmp(scratch2, MAP_TYPE);
- __ j(not_equal, &done);
-
- // Get the prototype from the initial map.
- __ mov(eax, FieldOperand(eax, Map::kPrototypeOffset));
-
- // All done: Return the prototype.
- __ bind(&done);
__ ret(0);
+}
- // Non-instance prototype: Fetch prototype from constructor field
- // in initial map.
- __ bind(&non_instance);
- __ mov(eax, FieldOperand(scratch1, Map::kConstructorOffset));
- __ ret(0);
+
+// Load a fast property out of a holder object (src). In-object properties
+// are loaded directly otherwise the property is loaded from the properties
+// fixed array.
+void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
+ Register dst, Register src,
+ JSObject* holder, int index) {
+ // Adjust for the number of properties stored in the holder.
+ index -= holder->map()->inobject_properties();
+ if (index < 0) {
+ // Get the property straight out of the holder.
+ int offset = holder->map()->instance_size() + (index * kPointerSize);
+ __ mov(dst, FieldOperand(src, offset));
+ } else {
+ // Calculate the offset into the properties array.
+ int offset = index * kPointerSize + Array::kHeaderSize;
+ __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
+ __ mov(dst, FieldOperand(dst, offset));
+ }
}
@@ -297,12 +275,8 @@
Register reg =
__ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
- // Get the properties array of the holder.
- __ mov(scratch1, FieldOperand(reg, JSObject::kPropertiesOffset));
-
- // Return the value from the properties array.
- int offset = index * kPointerSize + Array::kHeaderSize;
- __ mov(eax, FieldOperand(scratch1, offset));
+ // Get the value from the properties.
+ GenerateFastPropertyLoad(masm, eax, reg, holder, index);
__ ret(0);
}
@@ -442,8 +416,16 @@
return;
}
- // Get the properties array (optimistically).
- __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
+ // Adjust for the number of properties stored in the object. Even in the
+ // face of a transition we can use the old map here because the size of the
+ // object and the number of in-object properties is not going to change.
+ index -= object->map()->inobject_properties();
+
+ if (index >= 0) {
+ // Get the properties array (optimistically).
+ __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
+ }
+
if (transition != NULL) {
// Update the map of the object; no write barrier updating is
// needed because the map is never in new space.
@@ -451,14 +433,25 @@
Immediate(Handle<Map>(transition)));
}
- // Write to the properties array.
- int offset = index * kPointerSize + Array::kHeaderSize;
- __ mov(FieldOperand(scratch, offset), eax);
+ if (index < 0) {
+ // Set the property straight into the object.
+ int offset = object->map()->instance_size() + (index * kPointerSize);
+ __ mov(FieldOperand(receiver_reg, offset), eax);
- // Update the write barrier for the array address.
- // Pass the value being stored in the now unused name_reg.
- __ mov(name_reg, Operand(eax));
- __ RecordWrite(scratch, offset, name_reg, receiver_reg);
+ // Update the write barrier for the array address.
+ // Pass the value being stored in the now unused name_reg.
+ __ mov(name_reg, Operand(eax));
+ __ RecordWrite(receiver_reg, offset, name_reg, scratch);
+ } else {
+ // Write to the properties array.
+ int offset = index * kPointerSize + Array::kHeaderSize;
+ __ mov(FieldOperand(scratch, offset), eax);
+
+ // Update the write barrier for the array address.
+ // Pass the value being stored in the now unused name_reg.
+ __ mov(name_reg, Operand(eax));
+ __ RecordWrite(scratch, offset, name_reg, receiver_reg);
+ }
// Return the value (register eax).
__ ret(0);
@@ -516,10 +509,7 @@
Register reg =
__ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
- // Get the properties array of the holder and get the function from the field.
- int offset = index * kPointerSize + Array::kHeaderSize;
- __ mov(edi, FieldOperand(reg, JSObject::kPropertiesOffset));
- __ mov(edi, FieldOperand(edi, offset));
+ GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
// Check that the function really is a function.
__ test(edi, Immediate(kSmiTagMask));