return branchAdd32(cond, op1, dataTempRegister, dest);
}
+ Jump branchAdd32(ResultCondition cond, Address src, RegisterID dest)
+ {
+ load32(src, getCachedDataTempRegisterIDAndInvalidate());
+ return branchAdd32(cond, dest, dataTempRegister, dest);
+ }
+
Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
{
return branchAdd32(cond, dest, src, dest);
return branchAdd32(cond, dest, src, dest);
}
+ Jump branchAdd32(ResultCondition cond, Address src, RegisterID dest)
+ {
+ load32(src, dataTempRegister);
+ return branchAdd32(cond, dest, dataTempRegister, dest);
+ }
+
Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
{
return branchAdd32(cond, dest, imm, dest);
}
case MakeRope: {
+ node->setCanExit(true);
forNode(node).set(m_graph.m_vm.stringStructure.get());
break;
}
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
+ if (sumOverflows<int32_t>(left->length(), right->length())) {
+ throwOutOfMemoryError(exec);
+ return nullptr;
+ }
+
return JSRopeString::create(vm, left, right);
}
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
+ if (sumOverflows<int32_t>(a->length(), b->length(), c->length())) {
+ throwOutOfMemoryError(exec);
+ return nullptr;
+ }
+
return JSRopeString::create(vm, a, b, c);
}
m_jit.storePtr(TrustedImmPtr(0), JITCompiler::Address(resultGPR, JSRopeString::offsetOfFibers() + sizeof(WriteBarrier<JSString>) * i));
m_jit.load32(JITCompiler::Address(opGPRs[0], JSString::offsetOfFlags()), scratchGPR);
m_jit.load32(JITCompiler::Address(opGPRs[0], JSString::offsetOfLength()), allocatorGPR);
+ if (!ASSERT_DISABLED) {
+ JITCompiler::Jump ok = m_jit.branch32(
+ JITCompiler::GreaterThanOrEqual, allocatorGPR, TrustedImm32(0));
+ m_jit.breakpoint();
+ ok.link(&m_jit);
+ }
for (unsigned i = 1; i < numOpGPRs; ++i) {
m_jit.and32(JITCompiler::Address(opGPRs[i], JSString::offsetOfFlags()), scratchGPR);
- m_jit.add32(JITCompiler::Address(opGPRs[i], JSString::offsetOfLength()), allocatorGPR);
+ speculationCheck(
+ Uncountable, JSValueSource(), nullptr,
+ m_jit.branchAdd32(
+ JITCompiler::Overflow,
+ JITCompiler::Address(opGPRs[i], JSString::offsetOfLength()), allocatorGPR));
}
m_jit.and32(JITCompiler::TrustedImm32(JSString::Is8Bit), scratchGPR);
m_jit.store32(scratchGPR, JITCompiler::Address(resultGPR, JSString::offsetOfFlags()));
+ if (!ASSERT_DISABLED) {
+ JITCompiler::Jump ok = m_jit.branch32(
+ JITCompiler::GreaterThanOrEqual, allocatorGPR, TrustedImm32(0));
+ m_jit.breakpoint();
+ ok.link(&m_jit);
+ }
m_jit.store32(allocatorGPR, JITCompiler::Address(resultGPR, JSString::offsetOfLength()));
switch (numOpGPRs) {
return;
}
+ addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+
DataLabelPtr addressOfLinkedFunctionCheck;
BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
Jump slowCase = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(0));
END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
addSlowCase(slowCase);
- addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
ASSERT(m_callStructureStubCompilationInfo.size() == callLinkInfoIndex);
m_callStructureStubCompilationInfo.append(StructureStubCompilationInfo());
LLINT_END_IMPL(); \
} while (false)
+#define LLINT_RETURN_WITH_PC_ADJUSTMENT(value, pcAdjustment) do { \
+ JSValue __r_returnValue = (value); \
+ LLINT_CHECK_EXCEPTION(); \
+ LLINT_OP(1) = __r_returnValue; \
+ pc += (pcAdjustment); \
+ LLINT_END_IMPL(); \
+ } while (false)
+
#if ENABLE(VALUE_PROFILER)
#define LLINT_RETURN_PROFILED(opcode, value) do { \
JSValue __rp_returnValue = (value); \
JSObject* baseObject = asObject(baseVal);
ASSERT(!baseObject->structure()->typeInfo().implementsDefaultHasInstance());
if (baseObject->structure()->typeInfo().implementsHasInstance()) {
- pc += pc[4].u.operand;
- LLINT_RETURN(jsBoolean(baseObject->methodTable()->customHasInstance(baseObject, exec, value)));
+ JSValue result = jsBoolean(baseObject->methodTable()->customHasInstance(baseObject, exec, value));
+ LLINT_RETURN_WITH_PC_ADJUSTMENT(result, pc[4].u.operand);
}
}
LLINT_THROW(createInvalidParamError(exec, "instanceof", baseVal));
{
ASSERT(m_index == JSRopeString::s_maxInternalRopeLength);
JSString* jsString = m_jsString;
+ RELEASE_ASSERT(jsString);
m_jsString = jsStringBuilder(&m_vm);
m_index = 0;
append(jsString);
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2014 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
static JSString* create(VM& vm, PassRefPtr<StringImpl> value)
{
ASSERT(value);
- size_t length = value->length();
+ int32_t length = value->length();
+ RELEASE_ASSERT(length >= 0);
size_t cost = value->cost();
JSString* newString = new (NotNull, allocateCell<JSString>(vm.heap)) JSString(vm, value);
newString->finishCreation(vm, length, cost);
{
}
- void append(JSString* jsString)
+ bool append(JSString* jsString)
{
if (m_index == JSRopeString::s_maxInternalRopeLength)
expand();
+ if (static_cast<int32_t>(m_jsString->length() + jsString->length()) < 0) {
+ m_jsString = nullptr;
+ return false;
+ }
m_jsString->append(m_vm, m_index++, jsString);
+ return true;
}
JSRopeString* release()
{
+ RELEASE_ASSERT(m_jsString);
JSRopeString* tmp = m_jsString;
m_jsString = 0;
return tmp;
{
m_fibers[index].set(vm, this, jsString);
m_length += jsString->m_length;
+ RELEASE_ASSERT(static_cast<int32_t>(m_length) >= 0);
setIs8Bit(is8Bit() && jsString->is8Bit());
}
{
VM& vm = exec->vm();
- unsigned length1 = s1->length();
+ int32_t length1 = s1->length();
if (!length1)
return s2;
- unsigned length2 = s2->length();
+ int32_t length2 = s2->length();
if (!length2)
return s1;
- if ((length1 + length2) < length1)
+ if (sumOverflows<int32_t>(length1, length2))
return throwOutOfMemoryError(exec);
return JSRopeString::create(vm, s1, s2);
{
VM* vm = &exec->vm();
- unsigned length1 = u1.length();
- unsigned length2 = u2.length();
- unsigned length3 = u3.length();
+ int32_t length1 = u1.length();
+ int32_t length2 = u2.length();
+ int32_t length3 = u3.length();
+
+ if (length1 < 0 || length2 < 0 || length3 < 0)
+ return throwOutOfMemoryError(exec);
+
if (!length1)
return jsString(exec, jsString(vm, u2), jsString(vm, u3));
if (!length2)
if (!length3)
return jsString(exec, jsString(vm, u1), jsString(vm, u2));
- if ((length1 + length2) < length1)
- return throwOutOfMemoryError(exec);
- if ((length1 + length2 + length3) < length3)
+ if (sumOverflows<int32_t>(length1, length2, length3))
return throwOutOfMemoryError(exec);
return JSRopeString::create(exec->vm(), jsString(vm, u1), jsString(vm, u2), jsString(vm, u3));
VM* vm = &exec->vm();
JSRopeString::RopeBuilder ropeBuilder(*vm);
- unsigned oldLength = 0;
-
for (unsigned i = 0; i < count; ++i) {
JSValue v = strings[i].jsValue();
- ropeBuilder.append(v.toString(exec));
-
- if (ropeBuilder.length() < oldLength) // True for overflow
+ if (!ropeBuilder.append(v.toString(exec)))
return throwOutOfMemoryError(exec);
- oldLength = ropeBuilder.length();
}
return ropeBuilder.release();
JSRopeString::RopeBuilder ropeBuilder(*vm);
ropeBuilder.append(thisValue.toString(exec));
- unsigned oldLength = 0;
-
for (unsigned i = 0; i < exec->argumentCount(); ++i) {
JSValue v = exec->argument(i);
- ropeBuilder.append(v.toString(exec));
-
- if (ropeBuilder.length() < oldLength) // True for overflow
+ if (!ropeBuilder.append(v.toString(exec)))
return throwOutOfMemoryError(exec);
- oldLength = ropeBuilder.length();
}
return ropeBuilder.release();
else {
unsigned pos;
int len = s.length();
+ RELEASE_ASSERT(len >= 0);
if (a1.isUInt32())
pos = std::min<uint32_t>(a1.asUInt32(), len);
else {
return throwVMTypeError(exec);
String s = thisValue.toString(exec)->value(exec);
int len = s.length();
+ RELEASE_ASSERT(len >= 0);
JSValue a0 = exec->argument(0);
JSValue a1 = exec->argument(1);
JSValue a0 = exec->argument(0);
JSValue a1 = exec->argument(1);
int len = jsString->length();
+ RELEASE_ASSERT(len >= 0);
double start = a0.toNumber(exec);
double end;
int sSize = s.length();
if (!sSize)
return JSValue::encode(sVal);
+ RELEASE_ASSERT(sSize >= 0);
StringImpl* ourImpl = s.impl();
RefPtr<StringImpl> lower = ourImpl->lower();
--- /dev/null
+// Like make-large-string-jit.js, but tests MakeRope with three arguments and op_strcat
+// in the DFG and FTL JITs.
+
+var s = "s";
+
+function foo(a, b) {
+ return "t" + a + b;
+}
+
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i)
+ foo("a", "b");
+
+try {
+ for (var i = 0; i < 31; ++i)
+ s = foo(s, s);
+ print("Should not have gotten here.");
+ print("String length: " + s.length);
+ throw "Should not have gotten here.";
+} catch (e) {
+ if (e.message != "Out of memory")
+ throw "Wrong error: " + e;
+}
--- /dev/null
+// Like make-large-string.js, but tests MakeRope with two arguments in the DFG and FTL JITs.
+
+var s = "s";
+
+function foo(a, b) {
+ return a + b;
+}
+
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i)
+ foo("a", "b");
+
+try {
+ for (var i = 0; i < 31; ++i)
+ s = foo(s, s);
+ print("Should not have gotten here.");
+ print("String length: " + s.length);
+ throw "Should not have gotten here.";
+} catch (e) {
+ if (e.message != "Out of memory")
+ throw "Wrong error: " + e;
+}
--- /dev/null
+var s = "s";
+
+try {
+ for (var i = 0; i < 31; ++i)
+ s = "t" + s + s;
+ print("Should not have gotten here.");
+ print("String length: " + s.length);
+ throw "Should not have gotten here.";
+} catch (e) {
+ if (e.message != "Out of memory")
+ throw "Wrong error: " + e;
+}
--- /dev/null
+var s = "s";
+
+try {
+ for (var i = 0; i < 31; ++i)
+ s = s + s;
+ print("Should not have gotten here.");
+ print("String length: " + s.length);
+ throw "Should not have gotten here.";
+} catch (e) {
+ if (e.message != "Out of memory")
+ throw "Wrong error: " + e;
+}