+2011-01=31: Version 3.1.0
+ Performance improvements on all platforms.
+
+
2011-01-28: Version 3.0.12
Added support for strict mode parameter and object property
'gcc': {
'all': {
'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'],
- 'CXXFLAGS': ['$CCFLAGS', '-fno-rtti', '-fno-exceptions', '-fno-builtin-memcpy'],
+ 'CXXFLAGS': ['$CCFLAGS', '-fno-rtti', '-fno-exceptions'],
},
'visibility:hidden': {
# Use visibility=default to disable this.
*/
class V8EXPORT Context {
public:
- /** Returns the global object of the context. */
+ /**
+ * Returns the global proxy object or global object itself for
+ * detached contexts.
+ *
+ * Global proxy object is a thin wrapper whose prototype points to
+ * actual context's global object with the properties like Object, etc.
+ * This is done that way for security reasons (for more details see
+ * https://wiki.mozilla.org/Gecko:SplitWindow).
+ *
+ * Please note that changes to global proxy object prototype most probably
+ * would break VM---v8 expects only global object as a prototype of
+ * global proxy object.
+ *
+ * If DetachGlobal() has been invoked, Global() would return actual global
+ * object until global is reattached with ReattachGlobal().
+ */
Local<Object> Global();
/**
}
+void Assembler::vabs(const DwVfpRegister dst,
+ const DwVfpRegister src,
+ const Condition cond) {
+ emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 |
+ 0x5*B9 | B8 | 0x3*B6 | src.code());
+}
+
+
void Assembler::vadd(const DwVfpRegister dst,
const DwVfpRegister src1,
const DwVfpRegister src2,
ConversionMode mode = RoundToZero,
const Condition cond = al);
+ void vabs(const DwVfpRegister dst,
+ const DwVfpRegister src,
+ const Condition cond = al);
void vadd(const DwVfpRegister dst,
const DwVfpRegister src1,
const DwVfpRegister src2,
Register rhs);
+void ToNumberStub::Generate(MacroAssembler* masm) {
+ // The ToNumber stub takes one argument in eax.
+ Label check_heap_number, call_builtin;
+ __ tst(r0, Operand(kSmiTagMask));
+ __ b(ne, &check_heap_number);
+ __ Ret();
+
+ __ bind(&check_heap_number);
+ __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+ __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
+ __ cmp(r1, ip);
+ __ b(ne, &call_builtin);
+ __ Ret();
+
+ __ bind(&call_builtin);
+ __ push(r0);
+ __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_JS);
+}
+
+
void FastNewClosureStub::Generate(MacroAssembler* masm) {
// Create a new closure from the given function info in new
// space. Set the context to the current context in cp.
} else {
Format(instr, "vmov.f32'cond 'Sd, 'Sm");
}
+ } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
+ // vabs
+ Format(instr, "vabs'cond 'Dd, 'Dm");
} else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
DecodeVCVTBetweenDoubleAndSingle(instr);
} else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
Label no_conversion;
__ tst(result_register(), Operand(kSmiTagMask));
__ b(eq, &no_conversion);
- __ push(r0);
- __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
+ ToNumberStub convert_stub;
+ __ CallStub(&convert_stub);
__ bind(&no_conversion);
context()->Plug(result_register());
break;
// Call ToNumber only if operand is not a smi.
Label no_conversion;
__ JumpIfSmi(r0, &no_conversion);
- __ push(r0);
- __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
+ ToNumberStub convert_stub;
+ __ CallStub(&convert_stub);
__ bind(&no_conversion);
// Save result for postfix expressions.
0,
Safepoint::kNoDeoptimizationIndex);
// Overwrite the stored value of r0 with the result of the stub.
- __ str(r0, MemOperand(sp, DwVfpRegister::kNumAllocatableRegisters *
- kDoubleSize));
+ __ StoreToSafepointRegistersAndDoublesSlot(r0);
__ PopSafepointRegistersAndDoubles();
}
void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
+ ASSERT(instr->InputAt(0)->Equals(instr->result()));
Register input = ToRegister(instr->InputAt(0));
Register scratch = scratch0();
DeoptimizeIf(ne, instr->environment());
Label done;
-
- Label negative;
- __ ldr(scratch, FieldMemOperand(input, HeapNumber::kExponentOffset));
+ Register exponent = scratch0();
+ scratch = no_reg;
+ __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
// Check the sign of the argument. If the argument is positive, just
// return it. We do not need to patch the stack since |input| and
- // |result| are the same register and |input| will be restored
+ // |result| are the same register and |input| would be restored
// unchanged by popping safepoint registers.
- __ tst(scratch, Operand(HeapNumber::kSignMask));
- __ b(ne, &negative);
- __ jmp(&done);
+ __ tst(exponent, Operand(HeapNumber::kSignMask));
+ __ b(eq, &done);
- __ bind(&negative);
+ // Input is negative. Reverse its sign.
// Preserve the value of all registers.
__ PushSafepointRegisters();
- Register tmp = input.is(r0) ? r1 : r0;
- Register tmp2 = input.is(r2) ? r3 : r2;
- Register tmp3 = input.is(r4) ? r5 : r4;
+ // Registers were saved at the safepoint, so we can use
+ // many scratch registers.
+ Register tmp1 = input.is(r1) ? r0 : r1;
+ Register tmp2 = input.is(r2) ? r0 : r2;
+ Register tmp3 = input.is(r3) ? r0 : r3;
+ Register tmp4 = input.is(r4) ? r0 : r4;
+
+ // exponent: floating point exponent value.
Label allocated, slow;
- __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
- __ AllocateHeapNumber(tmp, tmp2, tmp3, scratch, &slow);
+ __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
+ __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
__ b(&allocated);
// Slow case: Call the runtime system to do the number allocation.
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
// Set the pointer to the new heap number in tmp.
- if (!tmp.is(r0)) __ mov(tmp, Operand(r0));
-
+ if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0));
// Restore input_reg after call to runtime.
- MemOperand input_register_slot = masm()->SafepointRegisterSlot(input);
- __ ldr(input, input_register_slot);
+ __ LoadFromSafepointRegisterSlot(input);
+ __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
__ bind(&allocated);
- __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kExponentOffset));
- __ bic(tmp2, tmp2, Operand(HeapNumber::kSignMask));
- __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kExponentOffset));
+ // exponent: floating point exponent value.
+ // tmp1: allocated heap number.
+ __ bic(exponent, exponent, Operand(HeapNumber::kSignMask));
+ __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
__ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
- __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kMantissaOffset));
+ __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
- __ str(tmp, input_register_slot);
+ __ str(tmp1, masm()->SafepointRegisterSlot(input));
__ PopSafepointRegisters();
__ bind(&done);
void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
- Label is_positive;
- uint32_t kSignMask = 0x80000000u;
Register input = ToRegister(instr->InputAt(0));
- __ tst(input, Operand(kSignMask));
- __ b(eq, &is_positive);
- __ rsb(input, input, Operand(0), SetCC);
+ __ cmp(input, Operand(0));
+ // We can make rsb conditional because the previous cmp instruction
+ // will clear the V (overflow) flag and rsb won't set this flag
+ // if input is positive.
+ __ rsb(input, input, Operand(0), SetCC, mi);
// Deoptimize on overflow.
DeoptimizeIf(vs, instr->environment());
- __ bind(&is_positive);
}
Representation r = instr->hydrogen()->value()->representation();
if (r.IsDouble()) {
DwVfpRegister input = ToDoubleRegister(instr->InputAt(0));
- // __ vabs(input, input);
- Abort("Double DoMathAbs unimplemented");
+ __ vabs(input, input);
} else if (r.IsInteger32()) {
EmitIntegerMathAbs(instr);
} else {
PopSafepointRegisters();
}
+void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register reg) {
+ str(reg, SafepointRegistersAndDoublesSlot(reg));
+}
+
+
void MacroAssembler::StoreToSafepointRegisterSlot(Register reg) {
str(reg, SafepointRegisterSlot(reg));
}
+void MacroAssembler::LoadFromSafepointRegisterSlot(Register reg) {
+ ldr(reg, SafepointRegisterSlot(reg));
+}
+
+
int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
// The registers are pushed starting with the highest encoding,
// which means that lowest encodings are closest to the stack pointer.
}
+MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
+ // General purpose registers are pushed last on the stack.
+ int doubles_size = DwVfpRegister::kNumAllocatableRegisters * kDoubleSize;
+ int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
+ return MemOperand(sp, doubles_size + register_offset);
+}
+
+
void MacroAssembler::Ldrd(Register dst1, Register dst2,
const MemOperand& src, Condition cond) {
ASSERT(src.rm().is(no_reg));
void PushSafepointRegistersAndDoubles();
void PopSafepointRegistersAndDoubles();
void StoreToSafepointRegisterSlot(Register reg);
+ void StoreToSafepointRegistersAndDoublesSlot(Register reg);
+ void LoadFromSafepointRegisterSlot(Register reg);
static int SafepointRegisterStackIndex(int reg_code);
static MemOperand SafepointRegisterSlot(Register reg);
+ static MemOperand SafepointRegistersAndDoublesSlot(Register reg);
// Load two consecutive registers with two consecutive memory locations.
void Ldrd(Register dst1,
int d = instr->VFPDRegValue(kSinglePrecision);
set_s_register_from_float(d, get_float_from_s_register(m));
}
+ } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
+ // vabs
+ double dm_value = get_double_from_d_register(vm);
+ double dd_value = fabs(dm_value);
+ set_d_register_from_double(vd, dd_value);
} else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
DecodeVCVTBetweenDoubleAndSingle(instr);
} else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
V(GenericUnaryOp) \
V(RevertToNumber) \
V(ToBoolean) \
+ V(ToNumber) \
V(CounterOp) \
V(ArgumentsAccess) \
V(RegExpExec) \
};
+class ToNumberStub: public CodeStub {
+ public:
+ ToNumberStub() { }
+
+ void Generate(MacroAssembler* masm);
+
+ private:
+ Major MajorKey() { return ToNumber; }
+ int MinorKey() { return 0; }
+ const char* GetName() { return "ToNumberStub"; }
+};
+
+
class FastNewClosureStub : public CodeStub {
public:
void Generate(MacroAssembler* masm);
// ECMA 262 - 15.9.5.5
function DateToLocaleString() {
- return DateToString.call(this);
+ return %_CallFunction(this, DateToString);
}
// do that either. Instead, we create a new function whose name
// property will return toGMTString.
function DateToGMTString() {
- return DateToUTCString.call(this);
+ return %_CallFunction(this, DateToUTCString);
}
I18NExtension* I18NExtension::extension_ = NULL;
// TODO(cira): maybe move JS code to a .js file and generata cc files from it?
+// TODO(cira): Remove v8 prefix from v8Locale once we have stable API.
const char* const I18NExtension::kSource =
- "Locale = function(optLocale) {"
+ "v8Locale = function(optLocale) {"
" native function NativeJSLocale();"
" var properties = NativeJSLocale(optLocale);"
" this.locale = properties.locale;"
" this.script = properties.script;"
" this.region = properties.region;"
"};"
- "Locale.availableLocales = function() {"
+ "v8Locale.availableLocales = function() {"
" native function NativeJSAvailableLocales();"
" return NativeJSAvailableLocales();"
"};"
- "Locale.prototype.maximizedLocale = function() {"
+ "v8Locale.prototype.maximizedLocale = function() {"
" native function NativeJSMaximizedLocale();"
- " return new Locale(NativeJSMaximizedLocale(this.locale));"
+ " return new v8Locale(NativeJSMaximizedLocale(this.locale));"
"};"
- "Locale.prototype.minimizedLocale = function() {"
+ "v8Locale.prototype.minimizedLocale = function() {"
" native function NativeJSMinimizedLocale();"
- " return new Locale(NativeJSMinimizedLocale(this.locale));"
+ " return new v8Locale(NativeJSMinimizedLocale(this.locale));"
"};"
- "Locale.prototype.displayLocale_ = function(displayLocale) {"
+ "v8Locale.prototype.displayLocale_ = function(displayLocale) {"
" var result = this.locale;"
" if (displayLocale !== undefined) {"
" result = displayLocale.locale;"
" }"
" return result;"
"};"
- "Locale.prototype.displayLanguage = function(optDisplayLocale) {"
+ "v8Locale.prototype.displayLanguage = function(optDisplayLocale) {"
" var displayLocale = this.displayLocale_(optDisplayLocale);"
" native function NativeJSDisplayLanguage();"
" return NativeJSDisplayLanguage(this.locale, displayLocale);"
"};"
- "Locale.prototype.displayScript = function(optDisplayLocale) {"
+ "v8Locale.prototype.displayScript = function(optDisplayLocale) {"
" var displayLocale = this.displayLocale_(optDisplayLocale);"
" native function NativeJSDisplayScript();"
" return NativeJSDisplayScript(this.locale, displayLocale);"
"};"
- "Locale.prototype.displayRegion = function(optDisplayLocale) {"
+ "v8Locale.prototype.displayRegion = function(optDisplayLocale) {"
" var displayLocale = this.displayLocale_(optDisplayLocale);"
" native function NativeJSDisplayRegion();"
" return NativeJSDisplayRegion(this.locale, displayLocale);"
"};"
- "Locale.prototype.displayName = function(optDisplayLocale) {"
+ "v8Locale.prototype.displayName = function(optDisplayLocale) {"
" var displayLocale = this.displayLocale_(optDisplayLocale);"
" native function NativeJSDisplayName();"
" return NativeJSDisplayName(this.locale, displayLocale);"
namespace internal {
#define __ ACCESS_MASM(masm)
+
+void ToNumberStub::Generate(MacroAssembler* masm) {
+ // The ToNumber stub takes one argument in eax.
+ NearLabel check_heap_number, call_builtin;
+ __ test(eax, Immediate(kSmiTagMask));
+ __ j(not_zero, &check_heap_number);
+ __ ret(0);
+
+ __ bind(&check_heap_number);
+ __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
+ __ cmp(Operand(ebx), Immediate(Factory::heap_number_map()));
+ __ j(not_equal, &call_builtin);
+ __ ret(0);
+
+ __ bind(&call_builtin);
+ __ pop(ecx); // Pop return address.
+ __ push(eax);
+ __ push(ecx); // Push return address.
+ __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
+}
+
+
void FastNewClosureStub::Generate(MacroAssembler* masm) {
// Create a new closure from the given function info in new
// space. Set the context to the current context in esi.
Label no_conversion;
__ test(result_register(), Immediate(kSmiTagMask));
__ j(zero, &no_conversion);
- __ push(result_register());
- __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
+ ToNumberStub convert_stub;
+ __ CallStub(&convert_stub);
__ bind(&no_conversion);
context()->Plug(result_register());
break;
__ test(eax, Immediate(kSmiTagMask));
__ j(zero, &no_conversion);
}
- __ push(eax);
- __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
+ ToNumberStub convert_stub;
+ __ CallStub(&convert_stub);
__ bind(&no_conversion);
// Save result for postfix expressions.
}
} else {
for (var p in val) {
- if (ObjectHasOwnProperty.call(val, p)) {
+ if (%_CallFunction(val, p, ObjectHasOwnProperty)) {
var newElement = Revive(val, p, reviver);
if (IS_UNDEFINED(newElement)) {
delete val[p];
if (IS_ARRAY(replacer)) {
var length = replacer.length;
for (var i = 0; i < length; i++) {
- if (ObjectHasOwnProperty.call(replacer, i)) {
+ if (%_CallFunction(replacer, i, ObjectHasOwnProperty)) {
var p = replacer[i];
var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
if (!IS_UNDEFINED(strP)) {
}
} else {
for (var p in value) {
- if (ObjectHasOwnProperty.call(value, p)) {
+ if (%_CallFunction(value, p, ObjectHasOwnProperty)) {
var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
if (!IS_UNDEFINED(strP)) {
var member = %QuoteJSONString(p) + ":";
// message on access.
var kAddMessageAccessorsMarker = { };
-
-function GetInstanceName(cons) {
- if (cons.length == 0) {
- return "";
- }
- var first = %StringToLowerCase(StringCharAt.call(cons, 0));
- if (kVowelSounds === 0) {
- kVowelSounds = {a: true, e: true, i: true, o: true, u: true, y: true};
- kCapitalVowelSounds = {a: true, e: true, i: true, o: true, u: true, h: true,
- f: true, l: true, m: true, n: true, r: true, s: true, x: true, y: true};
- }
- var vowel_mapping = kVowelSounds;
- if (cons.length > 1 && (StringCharAt.call(cons, 0) != first)) {
- // First char is upper case
- var second = %StringToLowerCase(StringCharAt.call(cons, 1));
- // Second char is upper case
- if (StringCharAt.call(cons, 1) != second) {
- vowel_mapping = kCapitalVowelSounds;
- }
- }
- var s = vowel_mapping[first] ? "an " : "a ";
- return s + cons;
-}
-
-
var kMessages = 0;
+var kReplacementMarkers =
+ [ "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7", "%8", "%9", "%10" ];
function FormatString(format, args) {
var result = format;
} catch (e) {
str = "#<error>";
}
- result = ArrayJoin.call(StringSplit.call(result, "%" + i), str);
+ var replacement_marker = kReplacementMarkers[i];
+ var split = %_CallFunction(result, replacement_marker, StringSplit);
+ result = %_CallFunction(split, str, ArrayJoin);
}
return result;
}
if (!constructorName || !IS_STRING(constructorName)) {
return ToStringCheckErrorObject(obj);
}
- return "#<" + GetInstanceName(constructorName) + ">";
+ return "#<" + constructorName + ">";
} else {
return ToStringCheckErrorObject(obj);
}
var line_ends = this.line_ends;
var start = line == 0 ? 0 : line_ends[line - 1] + 1;
var end = line_ends[line];
- if (end > 0 && StringCharAt.call(this.source, end - 1) == '\r') end--;
+ if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') end--;
var column = position - start;
// Adjust according to the offset within the resource.
var line_ends = this.line_ends;
var start = line == 0 ? 0 : line_ends[line - 1] + 1;
var end = line_ends[line];
- return StringSubstring.call(this.source, start, end);
+ return %_CallFunction(this.source, start, end, StringSubstring);
}
* Source text for this location.
*/
SourceLocation.prototype.sourceText = function () {
- return StringSubstring.call(this.script.source, this.start, this.end);
+ return %_CallFunction(this.script.source, this.start, this.end, StringSubstring);
};
* the line terminating characters (if any)
*/
SourceSlice.prototype.sourceText = function () {
- return StringSubstring.call(this.script.source, this.from_position, this.to_position);
+ return %_CallFunction(this.script.source,
+ this.from_position,
+ this.to_position,
+ StringSubstring);
};
CallSite.prototype.getTypeName = function () {
var constructor = this.receiver.constructor;
if (!constructor)
- return $Object.prototype.toString.call(this.receiver);
+ return %_CallFunction(this.receiver, ObjectToString);
var constructorName = constructor.name;
if (!constructorName)
- return $Object.prototype.toString.call(this.receiver);
+ return %_CallFunction(this.receiver, ObjectToString);
return constructorName;
};
// this function.
var ownName = this.fun.name;
if (ownName && this.receiver &&
- (ObjectLookupGetter.call(this.receiver, ownName) === this.fun ||
- ObjectLookupSetter.call(this.receiver, ownName) === this.fun ||
+ (%_CallFunction(this.receiver, ownName, ObjectLookupGetter) === this.fun ||
+ %_CallFunction(this.receiver, ownName, ObjectLookupSetter) === this.fun ||
this.receiver[ownName] === this.fun)) {
// To handle DontEnum properties we guess that the method has
// the same name as the function.
Mirror.prototype.toText = function() {
// Simpel to text which is used when on specialization in subclass.
- return "#<" + builtins.GetInstanceName(this.constructor.name) + ">";
+ return "#<" + this.constructor.name + ">";
}
* @extends Mirror
*/
function ValueMirror(type, value, transient) {
- Mirror.call(this, type);
+ %_CallFunction(this, type, Mirror);
this.value_ = value;
if (!transient) {
this.allocateHandle_();
* @extends ValueMirror
*/
function UndefinedMirror() {
- ValueMirror.call(this, UNDEFINED_TYPE, void 0);
+ %_CallFunction(this, UNDEFINED_TYPE, void 0, ValueMirror);
}
inherits(UndefinedMirror, ValueMirror);
* @extends ValueMirror
*/
function NullMirror() {
- ValueMirror.call(this, NULL_TYPE, null);
+ %_CallFunction(this, NULL_TYPE, null, ValueMirror);
}
inherits(NullMirror, ValueMirror);
* @extends ValueMirror
*/
function BooleanMirror(value) {
- ValueMirror.call(this, BOOLEAN_TYPE, value);
+ %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror);
}
inherits(BooleanMirror, ValueMirror);
* @extends ValueMirror
*/
function NumberMirror(value) {
- ValueMirror.call(this, NUMBER_TYPE, value);
+ %_CallFunction(this, NUMBER_TYPE, value, ValueMirror);
}
inherits(NumberMirror, ValueMirror);
* @extends ValueMirror
*/
function StringMirror(value) {
- ValueMirror.call(this, STRING_TYPE, value);
+ %_CallFunction(this, STRING_TYPE, value, ValueMirror);
}
inherits(StringMirror, ValueMirror);
* @extends ValueMirror
*/
function ObjectMirror(value, type, transient) {
- ValueMirror.call(this, type || OBJECT_TYPE, value, transient);
+ %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror);
}
inherits(ObjectMirror, ValueMirror);
name = this.className();
}
}
- return '#<' + builtins.GetInstanceName(name) + '>';
+ return '#<' + name + '>';
};
* @extends ObjectMirror
*/
function FunctionMirror(value) {
- ObjectMirror.call(this, value, FUNCTION_TYPE);
+ %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror);
this.resolved_ = true;
}
inherits(FunctionMirror, ObjectMirror);
function UnresolvedFunctionMirror(value) {
// Construct this using the ValueMirror as an unresolved function is not a
// real object but just a string.
- ValueMirror.call(this, FUNCTION_TYPE, value);
+ %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror);
this.propertyCount_ = 0;
this.elementCount_ = 0;
this.resolved_ = false;
* @extends ObjectMirror
*/
function ArrayMirror(value) {
- ObjectMirror.call(this, value);
+ %_CallFunction(this, value, ObjectMirror);
}
inherits(ArrayMirror, ObjectMirror);
* @extends ObjectMirror
*/
function DateMirror(value) {
- ObjectMirror.call(this, value);
+ %_CallFunction(this, value, ObjectMirror);
}
inherits(DateMirror, ObjectMirror);
* @extends ObjectMirror
*/
function RegExpMirror(value) {
- ObjectMirror.call(this, value, REGEXP_TYPE);
+ %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror);
}
inherits(RegExpMirror, ObjectMirror);
* @extends ObjectMirror
*/
function ErrorMirror(value) {
- ObjectMirror.call(this, value, ERROR_TYPE);
+ %_CallFunction(this, value, ERROR_TYPE, ObjectMirror);
}
inherits(ErrorMirror, ObjectMirror);
* @extends Mirror
*/
function PropertyMirror(mirror, name, details) {
- Mirror.call(this, PROPERTY_TYPE);
+ %_CallFunction(this, PROPERTY_TYPE, Mirror);
this.mirror_ = mirror;
this.name_ = name;
this.value_ = details[0];
* @extends Mirror
*/
function FrameMirror(break_id, index) {
- Mirror.call(this, FRAME_TYPE);
+ %_CallFunction(this, FRAME_TYPE, Mirror);
this.break_id_ = break_id;
this.index_ = index;
this.details_ = new FrameDetails(break_id, index);
* @extends Mirror
*/
function ScopeMirror(frame, index) {
- Mirror.call(this, SCOPE_TYPE);
+ %_CallFunction(this, SCOPE_TYPE, Mirror);
this.frame_index_ = frame.index_;
this.scope_index_ = index;
this.details_ = new ScopeDetails(frame, index);
* @extends Mirror
*/
function ScriptMirror(script) {
- Mirror.call(this, SCRIPT_TYPE);
+ %_CallFunction(this, SCRIPT_TYPE, Mirror);
this.script_ = script;
this.context_ = new ContextMirror(script.context_data);
this.allocateHandle_();
* @extends Mirror
*/
function ContextMirror(data) {
- Mirror.call(this, CONTEXT_TYPE);
+ %_CallFunction(this, CONTEXT_TYPE, Mirror);
this.data_ = data;
this.allocateHandle_();
}
var multiline = false;
for (var i = 0; i < flags.length; i++) {
- var c = StringCharAt.call(flags, i);
+ var c = %_CallFunction(flags, i, StringCharAt);
switch (c) {
case 'g':
// Allow duplicate flags to be consistent with JSC and others.
if (!result.IsProperty()) {
return Heap::undefined_value();
}
- if (result.type() == CALLBACKS) {
- Object* structure = result.GetCallbackObject();
- if (structure->IsProxy() || structure->IsAccessorInfo()) {
- // Property that is internally implemented as a callback or
- // an API defined callback.
- Object* value;
- { MaybeObject* maybe_value = obj->GetPropertyWithCallback(
- *obj, structure, *name, result.holder());
- if (!maybe_value->ToObject(&value)) return maybe_value;
- }
- elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
- elms->set(VALUE_INDEX, value);
- elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly()));
- } else if (structure->IsFixedArray()) {
- // __defineGetter__/__defineSetter__ callback.
- elms->set(IS_ACCESSOR_INDEX, Heap::true_value());
- elms->set(GETTER_INDEX, FixedArray::cast(structure)->get(0));
- elms->set(SETTER_INDEX, FixedArray::cast(structure)->get(1));
- } else {
- return Heap::undefined_value();
- }
+
+ elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!result.IsDontEnum()));
+ elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!result.IsDontDelete()));
+
+ bool is_js_accessor = (result.type() == CALLBACKS) &&
+ (result.GetCallbackObject()->IsFixedArray());
+
+ if (is_js_accessor) {
+ // __defineGetter__/__defineSetter__ callback.
+ FixedArray* structure = FixedArray::cast(result.GetCallbackObject());
+ elms->set(IS_ACCESSOR_INDEX, Heap::true_value());
+ elms->set(GETTER_INDEX, structure->get(0));
+ elms->set(SETTER_INDEX, structure->get(1));
} else {
elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
- elms->set(VALUE_INDEX, result.GetLazyValue());
elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly()));
+
+ PropertyAttributes attrs;
+ Object* value;
+ { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs);
+ if (!maybe_value->ToObject(&value)) return maybe_value;
+ }
+ elms->set(VALUE_INDEX, value);
}
- elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!result.IsDontEnum()));
- elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!result.IsDontDelete()));
return *desc;
}
// NOTE these macros are used by the SCons build script so their names
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
-#define MINOR_VERSION 0
-#define BUILD_NUMBER 12
-#define PATCH_LEVEL 0
+#define MINOR_VERSION 1
+#define BUILD_NUMBER 0
+#define PATCH_LEVEL 1
#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the
namespace internal {
#define __ ACCESS_MASM(masm)
+
+void ToNumberStub::Generate(MacroAssembler* masm) {
+ // The ToNumber stub takes one argument in eax.
+ NearLabel check_heap_number, call_builtin;
+ __ SmiTest(rax);
+ __ j(not_zero, &check_heap_number);
+ __ Ret();
+
+ __ bind(&check_heap_number);
+ __ Move(rbx, Factory::heap_number_map());
+ __ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
+ __ j(not_equal, &call_builtin);
+ __ Ret();
+
+ __ bind(&call_builtin);
+ __ pop(rcx); // Pop return address.
+ __ push(rax);
+ __ push(rcx); // Push return address.
+ __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
+}
+
+
void FastNewClosureStub::Generate(MacroAssembler* masm) {
// Create a new closure from the given function info in new
// space. Set the context to the current context in rsi.
Label no_conversion;
Condition is_smi = masm_->CheckSmi(result_register());
__ j(is_smi, &no_conversion);
- __ push(result_register());
- __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
+ ToNumberStub convert_stub;
+ __ CallStub(&convert_stub);
__ bind(&no_conversion);
context()->Plug(result_register());
break;
Condition is_smi;
is_smi = masm_->CheckSmi(rax);
__ j(is_smi, &no_conversion);
- __ push(rax);
- __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
+ ToNumberStub convert_stub;
+ __ CallStub(&convert_stub);
__ bind(&no_conversion);
// Save result for postfix expressions.
v8::HandleScope scope;
v8::V8::AddMessageListener(check_reference_error_message);
LocalContext context;
+ CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
+ CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
CompileRun("ReferenceError.prototype.toString ="
" function() { return 'Whoops' }");
CompileRun("asdf;");
v8::Handle<Value> value;
// Access blocked property
- value = v8_compile("other.blocked_prop = 1")->Run();
- value = v8_compile("other.blocked_prop")->Run();
+ value = CompileRun("other.blocked_prop = 1");
+ value = CompileRun("other.blocked_prop");
CHECK(value->IsUndefined());
- value = v8_compile("propertyIsEnumerable.call(other, 'blocked_prop')")->Run();
+ value = CompileRun(
+ "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
+ CHECK(value->IsUndefined());
+
+ value = CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')");
CHECK(value->IsFalse());
// Access accessible property
- value = v8_compile("other.accessible_prop = 3")->Run();
+ value = CompileRun("other.accessible_prop = 3");
CHECK(value->IsNumber());
CHECK_EQ(3, value->Int32Value());
CHECK_EQ(3, g_echo_value);
- value = v8_compile("other.accessible_prop")->Run();
+ value = CompileRun("other.accessible_prop");
CHECK(value->IsNumber());
CHECK_EQ(3, value->Int32Value());
- value =
- v8_compile("propertyIsEnumerable.call(other, 'accessible_prop')")->Run();
+ value = CompileRun(
+ "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
+ CHECK(value->IsNumber());
+ CHECK_EQ(3, value->Int32Value());
+
+ value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
CHECK(value->IsTrue());
// Enumeration doesn't enumerate accessors from inaccessible objects in
// the prototype chain even if the accessors are in themselves accessible.
- Local<Value> result =
+ value =
CompileRun("(function(){var obj = {'__proto__':other};"
"for (var p in obj)"
" if (p == 'accessible_prop' || p == 'blocked_prop') {"
" return false;"
" }"
"return true;})()");
- CHECK(result->IsTrue());
+ CHECK(value->IsTrue());
context1->Exit();
context0->Exit();
" var str = String(e);"
" if (str.indexOf('TypeError') == -1) return 1;"
" if (str.indexOf('[object Fun]') != -1) return 2;"
- " if (str.indexOf('#<a Fun>') == -1) return 3;"
+ " if (str.indexOf('#<Fun>') == -1) return 3;"
" return 0;"
" }"
" return 4;"
double d;
double e;
double f;
+ double g;
+ double h;
int i;
float x;
float y;
__ vmov(s31, lr);
__ vcvt_f64_s32(d4, s31);
__ vstr(d4, r4, OFFSET_OF(T, f));
+
+ // Test vabs.
+ __ vldr(d1, r4, OFFSET_OF(T, g));
+ __ vabs(d0, d1);
+ __ vstr(d0, r4, OFFSET_OF(T, g));
+ __ vldr(d2, r4, OFFSET_OF(T, h));
+ __ vabs(d0, d2);
+ __ vstr(d0, r4, OFFSET_OF(T, h));
+
__ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
CodeDesc desc;
t.d = 0.0;
t.e = 0.0;
t.f = 0.0;
+ t.g = -2718.2818;
+ t.h = 31415926.5;
t.i = 0;
t.x = 4.5;
t.y = 9.0;
CHECK_EQ(4.5, t.y);
CHECK_EQ(9.0, t.x);
CHECK_EQ(2, t.i);
+ CHECK_EQ(2718.2818, t.g);
+ CHECK_EQ(31415926.5, t.h);
CHECK_EQ(42.0, t.f);
CHECK_EQ(1.0, t.e);
CHECK_EQ(1.000000059604644775390625, t.d);
COMPARE(vmov(s31, r10),
"ee0faa90 vmov s31, r10");
+ COMPARE(vabs(d0, d1),
+ "eeb00bc1 vabs d0, d1");
+ COMPARE(vabs(d3, d4, mi),
+ "4eb03bc4 vabsmi d3, d4");
+
COMPARE(vadd(d0, d1, d2),
"ee310b02 vadd.f64 d0, d1, d2");
COMPARE(vadd(d3, d4, d5, mi),
// 1: Call distance on Point where distance is a direct property
// 2: Call on function an array element 2
// 3: [anonymous]
- assertEquals("#<a Point>.distanceTo(p=#<a Point>)", exec_state.frame(0).invocationText());
- assertEquals("#<a Point>.distanceTo(p=#<a Point>)", exec_state.frame(1).invocationText());
- assertEquals("#<an Array>[2](aka distance)(p=#<a Point>, q=#<a Point>)", exec_state.frame(2).invocationText());
+ assertEquals("#<Point>.distanceTo(p=#<Point>)", exec_state.frame(0).invocationText());
+ assertEquals("#<Point>.distanceTo(p=#<Point>)", exec_state.frame(1).invocationText());
+ assertEquals("#<Array>[2](aka distance)(p=#<Point>, q=#<Point>)", exec_state.frame(2).invocationText());
assertEquals("[anonymous]()", exec_state.frame(3).invocationText());
listenerCalled = true;
} else {