Commit 06360928 authored by danno@chromium.org's avatar danno@chromium.org

Add a faster API for creating v8::Integer objects

In WebKit, we have a small integer cache because calling v8::Integer::New is
slow. This patch adds a faster API for creating integers that requires the
caller to supply the v8::Isolate, saving us the work of looking up the isolate
in thread-local storage.

BUG=

Review URL: https://codereview.chromium.org/11212004
Patch from Adam Barth <abarth@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12773 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a0c9856b
...@@ -1389,6 +1389,8 @@ class Integer : public Number { ...@@ -1389,6 +1389,8 @@ class Integer : public Number {
public: public:
V8EXPORT static Local<Integer> New(int32_t value); V8EXPORT static Local<Integer> New(int32_t value);
V8EXPORT static Local<Integer> NewFromUnsigned(uint32_t value); V8EXPORT static Local<Integer> NewFromUnsigned(uint32_t value);
V8EXPORT static Local<Integer> New(int32_t value, Isolate*);
V8EXPORT static Local<Integer> NewFromUnsigned(uint32_t value, Isolate*);
V8EXPORT int64_t Value() const; V8EXPORT int64_t Value() const;
static inline Integer* Cast(v8::Value* obj); static inline Integer* Cast(v8::Value* obj);
private: private:
......
...@@ -5228,24 +5228,39 @@ Local<Number> v8::Number::New(double value) { ...@@ -5228,24 +5228,39 @@ Local<Number> v8::Number::New(double value) {
Local<Integer> v8::Integer::New(int32_t value) { Local<Integer> v8::Integer::New(int32_t value) {
i::Isolate* isolate = i::Isolate::UncheckedCurrent(); i::Isolate* isolate = i::Isolate::UncheckedCurrent();
EnsureInitializedForIsolate(isolate, "v8::Integer::New()"); EnsureInitializedForIsolate(isolate, "v8::Integer::New()");
return v8::Integer::New(value, reinterpret_cast<Isolate*>(isolate));
}
Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::Integer::NewFromUnsigned()");
return Integer::NewFromUnsigned(value, reinterpret_cast<Isolate*>(isolate));
}
Local<Integer> v8::Integer::New(int32_t value, Isolate* isolate) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
ASSERT(internal_isolate->IsInitialized());
if (i::Smi::IsValid(value)) { if (i::Smi::IsValid(value)) {
return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value), return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
isolate)); internal_isolate));
} }
ENTER_V8(isolate); ENTER_V8(internal_isolate);
i::Handle<i::Object> result = isolate->factory()->NewNumber(value); i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
return Utils::IntegerToLocal(result); return Utils::IntegerToLocal(result);
} }
Local<Integer> Integer::NewFromUnsigned(uint32_t value) { Local<Integer> v8::Integer::NewFromUnsigned(uint32_t value, Isolate* isolate) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
ASSERT(internal_isolate->IsInitialized());
bool fits_into_int32_t = (value & (1 << 31)) == 0; bool fits_into_int32_t = (value & (1 << 31)) == 0;
if (fits_into_int32_t) { if (fits_into_int32_t) {
return Integer::New(static_cast<int32_t>(value)); return Integer::New(static_cast<int32_t>(value), isolate);
} }
i::Isolate* isolate = i::Isolate::Current(); ENTER_V8(internal_isolate);
ENTER_V8(isolate); i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
i::Handle<i::Object> result = isolate->factory()->NewNumber(value);
return Utils::IntegerToLocal(result); return Utils::IntegerToLocal(result);
} }
......
...@@ -969,22 +969,33 @@ THREADED_TEST(FindInstanceInPrototypeChain) { ...@@ -969,22 +969,33 @@ THREADED_TEST(FindInstanceInPrototypeChain) {
THREADED_TEST(TinyInteger) { THREADED_TEST(TinyInteger) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
int32_t value = 239; int32_t value = 239;
Local<v8::Integer> value_obj = v8::Integer::New(value); Local<v8::Integer> value_obj = v8::Integer::New(value);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value()); CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
value_obj = v8::Integer::New(value, isolate);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
} }
THREADED_TEST(BigSmiInteger) { THREADED_TEST(BigSmiInteger) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
int32_t value = i::Smi::kMaxValue; int32_t value = i::Smi::kMaxValue;
// We cannot add one to a Smi::kMaxValue without wrapping. // We cannot add one to a Smi::kMaxValue without wrapping.
if (i::kSmiValueSize < 32) { if (i::kSmiValueSize < 32) {
CHECK(i::Smi::IsValid(value)); CHECK(i::Smi::IsValid(value));
CHECK(!i::Smi::IsValid(value + 1)); CHECK(!i::Smi::IsValid(value + 1));
Local<v8::Integer> value_obj = v8::Integer::New(value); Local<v8::Integer> value_obj = v8::Integer::New(value);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value()); CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
value_obj = v8::Integer::New(value, isolate);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
} }
} }
...@@ -992,6 +1003,8 @@ THREADED_TEST(BigSmiInteger) { ...@@ -992,6 +1003,8 @@ THREADED_TEST(BigSmiInteger) {
THREADED_TEST(BigInteger) { THREADED_TEST(BigInteger) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
// We cannot add one to a Smi::kMaxValue without wrapping. // We cannot add one to a Smi::kMaxValue without wrapping.
if (i::kSmiValueSize < 32) { if (i::kSmiValueSize < 32) {
// The casts allow this to compile, even if Smi::kMaxValue is 2^31-1. // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
...@@ -1000,8 +1013,12 @@ THREADED_TEST(BigInteger) { ...@@ -1000,8 +1013,12 @@ THREADED_TEST(BigInteger) {
static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1); static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
CHECK(value > i::Smi::kMaxValue); CHECK(value > i::Smi::kMaxValue);
CHECK(!i::Smi::IsValid(value)); CHECK(!i::Smi::IsValid(value));
Local<v8::Integer> value_obj = v8::Integer::New(value); Local<v8::Integer> value_obj = v8::Integer::New(value);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value()); CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
value_obj = v8::Integer::New(value, isolate);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
} }
} }
...@@ -1009,42 +1026,66 @@ THREADED_TEST(BigInteger) { ...@@ -1009,42 +1026,66 @@ THREADED_TEST(BigInteger) {
THREADED_TEST(TinyUnsignedInteger) { THREADED_TEST(TinyUnsignedInteger) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
uint32_t value = 239; uint32_t value = 239;
Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value); Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value()); CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
value_obj = v8::Integer::NewFromUnsigned(value, isolate);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
} }
THREADED_TEST(BigUnsignedSmiInteger) { THREADED_TEST(BigUnsignedSmiInteger) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue); uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
CHECK(i::Smi::IsValid(value)); CHECK(i::Smi::IsValid(value));
CHECK(!i::Smi::IsValid(value + 1)); CHECK(!i::Smi::IsValid(value + 1));
Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value); Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value()); CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
value_obj = v8::Integer::NewFromUnsigned(value, isolate);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
} }
THREADED_TEST(BigUnsignedInteger) { THREADED_TEST(BigUnsignedInteger) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1; uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue)); CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
CHECK(!i::Smi::IsValid(value)); CHECK(!i::Smi::IsValid(value));
Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value); Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value()); CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
value_obj = v8::Integer::NewFromUnsigned(value, isolate);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
} }
THREADED_TEST(OutOfSignedRangeUnsignedInteger) { THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1; uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
uint32_t value = INT32_MAX_AS_UINT + 1; uint32_t value = INT32_MAX_AS_UINT + 1;
CHECK(value > INT32_MAX_AS_UINT); // No overflow. CHECK(value > INT32_MAX_AS_UINT); // No overflow.
Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value); Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value()); CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
value_obj = v8::Integer::NewFromUnsigned(value, isolate);
CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment