Version 3.8.8
Limited number of loop iterations in Heap::ReserveSpace (Chromium issue 99027).
Fixed solaris build (VirtualMemory) (issue 1761).
Fixed strict vs. non-strict handling of function proxies in higher-order array and string methods.
Enabled asynchronous remote debugging with d8 (issue 1691).
Stability and performance improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@10476 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 219d354..583453a 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -1031,14 +1031,25 @@
__ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift));
__ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset));
__ eor(r3, r3, Operand(r4, ASR, String::kHashShift));
- __ And(r3, r3, Operand(KeyedLookupCache::kCapacityMask));
+ int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
+ __ And(r3, r3, Operand(mask));
// Load the key (consisting of map and symbol) from the cache and
// check for match.
+ Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(isolate);
__ mov(r4, Operand(cache_keys));
__ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1));
+ // Move r4 to second entry.
+ __ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex));
+ __ cmp(r2, r5);
+ __ b(ne, &try_second_entry);
+ __ ldr(r5, MemOperand(r4, -kPointerSize)); // Load symbol
+ __ cmp(r0, r5);
+ __ b(eq, &hit_on_first_entry);
+
+ __ bind(&try_second_entry);
__ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); // Move r4 to symbol.
__ cmp(r2, r5);
__ b(ne, &slow);
@@ -1053,6 +1064,18 @@
// r3 : lookup cache index
ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(isolate);
+
+ // Hit on second entry.
+ __ mov(r4, Operand(cache_field_offsets));
+ __ add(r3, r3, Operand(1));
+ __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
+ __ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
+ __ sub(r5, r5, r6, SetCC);
+ __ b(ge, &property_array_property);
+ __ jmp(&load_in_object_property);
+
+ // Hit on first entry.
+ __ bind(&hit_on_first_entry);
__ mov(r4, Operand(cache_field_offsets));
__ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
__ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
@@ -1060,6 +1083,7 @@
__ b(ge, &property_array_property);
// Load in-object property.
+ __ bind(&load_in_object_property);
__ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset));
__ add(r6, r6, r5); // Index from start of object.
__ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag.
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 0e050fe..0807857 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2387,7 +2387,7 @@
Handle<String> name) {
LookupResult lookup(isolate());
type->LookupInDescriptors(NULL, *name, &lookup);
- ASSERT(lookup.IsProperty() &&
+ ASSERT(lookup.IsFound() &&
(lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
if (lookup.type() == FIELD) {
int index = lookup.GetLocalFieldIndexFromMap(*type);
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index cf2d4e2..33fbee5 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -1179,7 +1179,7 @@
// and CALLBACKS, so inline only them, other cases may be added
// later.
bool compile_followup_inline = false;
- if (lookup->IsProperty() && lookup->IsCacheable()) {
+ if (lookup->IsFound() && lookup->IsCacheable()) {
if (lookup->type() == FIELD) {
compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS &&
diff --git a/src/ast.cc b/src/ast.cc
index 7c5e3a7..580a485 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -746,7 +746,7 @@
&& type->prototype()->IsJSObject()) {
holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
type = Handle<Map>(holder()->map());
- } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
+ } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) {
target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
return true;
} else {
@@ -760,7 +760,7 @@
LookupResult* lookup) {
target_ = Handle<JSFunction>::null();
cell_ = Handle<JSGlobalPropertyCell>::null();
- ASSERT(lookup->IsProperty() &&
+ ASSERT(lookup->IsFound() &&
lookup->type() == NORMAL &&
lookup->holder() == *global);
cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(lookup));
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 752b220..cedb0ef 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1099,11 +1099,11 @@
#ifdef DEBUG
LookupResult lookup(isolate);
result->LocalLookup(heap->callee_symbol(), &lookup);
- ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
+ ASSERT(lookup.IsFound() && (lookup.type() == FIELD));
ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsCalleeIndex);
result->LocalLookup(heap->length_symbol(), &lookup);
- ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
+ ASSERT(lookup.IsFound() && (lookup.type() == FIELD));
ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex);
ASSERT(result->map()->inobject_properties() > Heap::kArgumentsCalleeIndex);
@@ -1197,7 +1197,7 @@
#ifdef DEBUG
LookupResult lookup(isolate);
result->LocalLookup(heap->length_symbol(), &lookup);
- ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
+ ASSERT(lookup.IsFound() && (lookup.type() == FIELD));
ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex);
ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex);
diff --git a/src/d8-debug.cc b/src/d8-debug.cc
index 1cbc0b3..de0faa8 100644
--- a/src/d8-debug.cc
+++ b/src/d8-debug.cc
@@ -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:
@@ -310,9 +310,7 @@
Handle<Value> request =
Shell::DebugCommandToJSONRequest(String::New(command));
if (try_catch.HasCaught()) {
- v8::String::Utf8Value exception(try_catch.Exception());
- const char* exception_string = Shell::ToCString(exception);
- printf("%s\n", exception_string);
+ Shell::ReportException(&try_catch);
PrintPrompt();
return;
}
diff --git a/src/d8-readline.cc b/src/d8-readline.cc
index 679c536..ed7721c 100644
--- a/src/d8-readline.cc
+++ b/src/d8-readline.cc
@@ -91,7 +91,11 @@
Handle<String> ReadLineEditor::Prompt(const char* prompt) {
- char* result = readline(prompt);
+ char* result = NULL;
+ { // Release lock for blocking input.
+ Unlocker unlock(Isolate::GetCurrent());
+ result = readline(prompt);
+ }
if (result != NULL) {
AddHistory(result);
} else {
diff --git a/src/d8.cc b/src/d8.cc
index b612c48..bfb9944 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -241,7 +241,12 @@
// Continue reading if the line ends with an escape '\\' or the line has
// not been fully read into the buffer yet (does not end with '\n').
// If fgets gets an error, just give up.
- if (fgets(buffer, kBufferSize, stdin) == NULL) return Handle<String>();
+ char* input = NULL;
+ { // Release lock for blocking input.
+ Unlocker unlock(Isolate::GetCurrent());
+ input = fgets(buffer, kBufferSize, stdin);
+ }
+ if (input == NULL) return Handle<String>();
length = static_cast<int>(strlen(buffer));
if (length == 0) {
return accumulator;
@@ -526,6 +531,10 @@
void Shell::ReportException(v8::TryCatch* try_catch) {
HandleScope handle_scope;
+#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
+ bool enter_context = !Context::InContext();
+ if (enter_context) utility_context_->Enter();
+#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
v8::String::Utf8Value exception(try_catch->Exception());
const char* exception_string = ToCString(exception);
Handle<Message> message = try_catch->Message();
@@ -560,6 +569,9 @@
}
}
printf("\n");
+#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
+ if (enter_context) utility_context_->Exit();
+#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
}
@@ -597,6 +609,12 @@
Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
return val;
}
+
+
+void Shell::DispatchDebugMessages() {
+ v8::Context::Scope scope(Shell::evaluation_context_);
+ v8::Debug::ProcessDebugMessages();
+}
#endif // ENABLE_DEBUGGER_SUPPORT
#endif // V8_SHARED
@@ -866,6 +884,7 @@
// Start the debugger agent if requested.
if (i::FLAG_debugger_agent) {
v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
+ v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true);
}
#endif // ENABLE_DEBUGGER_SUPPORT
#endif // V8_SHARED
diff --git a/src/d8.h b/src/d8.h
index e9b417b..60a8c1b 100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -266,12 +266,13 @@
size_t buckets);
static void AddHistogramSample(void* histogram, int sample);
static void MapCounters(const char* name);
-#endif // V8_SHARED
#ifdef ENABLE_DEBUGGER_SUPPORT
static Handle<Object> DebugMessageDetails(Handle<String> message);
static Handle<Value> DebugCommandToJSONRequest(Handle<String> command);
-#endif
+ static void DispatchDebugMessages();
+#endif // ENABLE_DEBUGGER_SUPPORT
+#endif // V8_SHARED
#ifdef WIN32
#undef Yield
diff --git a/src/extensions/experimental/break-iterator.cc b/src/extensions/experimental/break-iterator.cc
deleted file mode 100644
index e695a3e..0000000
--- a/src/extensions/experimental/break-iterator.cc
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/extensions/experimental/break-iterator.h"
-
-#include <string.h>
-
-#include "unicode/brkiter.h"
-#include "unicode/locid.h"
-#include "unicode/rbbi.h"
-
-namespace v8 {
-namespace internal {
-
-v8::Persistent<v8::FunctionTemplate> BreakIterator::break_iterator_template_;
-
-icu::BreakIterator* BreakIterator::UnpackBreakIterator(
- v8::Handle<v8::Object> obj) {
- if (break_iterator_template_->HasInstance(obj)) {
- return static_cast<icu::BreakIterator*>(
- obj->GetPointerFromInternalField(0));
- }
-
- return NULL;
-}
-
-icu::UnicodeString* BreakIterator::ResetAdoptedText(
- v8::Handle<v8::Object> obj, v8::Handle<v8::Value> value) {
- // Get the previous value from the internal field.
- icu::UnicodeString* text = static_cast<icu::UnicodeString*>(
- obj->GetPointerFromInternalField(1));
- delete text;
-
- // Assign new value to the internal pointer.
- v8::String::Value text_value(value);
- text = new icu::UnicodeString(
- reinterpret_cast<const UChar*>(*text_value), text_value.length());
- obj->SetPointerInInternalField(1, text);
-
- // Return new unicode string pointer.
- return text;
-}
-
-void BreakIterator::DeleteBreakIterator(v8::Persistent<v8::Value> object,
- void* param) {
- v8::Persistent<v8::Object> persistent_object =
- v8::Persistent<v8::Object>::Cast(object);
-
- // First delete the hidden C++ object.
- // Unpacking should never return NULL here. That would only happen if
- // this method is used as the weak callback for persistent handles not
- // pointing to a break iterator.
- delete UnpackBreakIterator(persistent_object);
-
- delete static_cast<icu::UnicodeString*>(
- persistent_object->GetPointerFromInternalField(1));
-
- // Then dispose of the persistent handle to JS object.
- persistent_object.Dispose();
-}
-
-// Throws a JavaScript exception.
-static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
- // Returns undefined, and schedules an exception to be thrown.
- return v8::ThrowException(v8::Exception::Error(
- v8::String::New("BreakIterator method called on an object "
- "that is not a BreakIterator.")));
-}
-
-v8::Handle<v8::Value> BreakIterator::BreakIteratorAdoptText(
- const v8::Arguments& args) {
- if (args.Length() != 1 || !args[0]->IsString()) {
- return v8::ThrowException(v8::Exception::SyntaxError(
- v8::String::New("Text input is required.")));
- }
-
- icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
- if (!break_iterator) {
- return ThrowUnexpectedObjectError();
- }
-
- break_iterator->setText(*ResetAdoptedText(args.Holder(), args[0]));
-
- return v8::Undefined();
-}
-
-v8::Handle<v8::Value> BreakIterator::BreakIteratorFirst(
- const v8::Arguments& args) {
- icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
- if (!break_iterator) {
- return ThrowUnexpectedObjectError();
- }
-
- return v8::Int32::New(break_iterator->first());
-}
-
-v8::Handle<v8::Value> BreakIterator::BreakIteratorNext(
- const v8::Arguments& args) {
- icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
- if (!break_iterator) {
- return ThrowUnexpectedObjectError();
- }
-
- return v8::Int32::New(break_iterator->next());
-}
-
-v8::Handle<v8::Value> BreakIterator::BreakIteratorCurrent(
- const v8::Arguments& args) {
- icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
- if (!break_iterator) {
- return ThrowUnexpectedObjectError();
- }
-
- return v8::Int32::New(break_iterator->current());
-}
-
-v8::Handle<v8::Value> BreakIterator::BreakIteratorBreakType(
- const v8::Arguments& args) {
- icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
- if (!break_iterator) {
- return ThrowUnexpectedObjectError();
- }
-
- // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
- icu::RuleBasedBreakIterator* rule_based_iterator =
- static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
- int32_t status = rule_based_iterator->getRuleStatus();
- // Keep return values in sync with JavaScript BreakType enum.
- if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
- return v8::Int32::New(UBRK_WORD_NONE);
- } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
- return v8::Int32::New(UBRK_WORD_NUMBER);
- } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
- return v8::Int32::New(UBRK_WORD_LETTER);
- } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
- return v8::Int32::New(UBRK_WORD_KANA);
- } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
- return v8::Int32::New(UBRK_WORD_IDEO);
- } else {
- return v8::Int32::New(-1);
- }
-}
-
-v8::Handle<v8::Value> BreakIterator::JSBreakIterator(
- const v8::Arguments& args) {
- v8::HandleScope handle_scope;
-
- if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
- return v8::ThrowException(v8::Exception::SyntaxError(
- v8::String::New("Locale and iterator type are required.")));
- }
-
- v8::String::Utf8Value locale(args[0]);
- icu::Locale icu_locale(*locale);
-
- UErrorCode status = U_ZERO_ERROR;
- icu::BreakIterator* break_iterator = NULL;
- v8::String::Utf8Value type(args[1]);
- if (!strcmp(*type, "character")) {
- break_iterator =
- icu::BreakIterator::createCharacterInstance(icu_locale, status);
- } else if (!strcmp(*type, "word")) {
- break_iterator =
- icu::BreakIterator::createWordInstance(icu_locale, status);
- } else if (!strcmp(*type, "sentence")) {
- break_iterator =
- icu::BreakIterator::createSentenceInstance(icu_locale, status);
- } else if (!strcmp(*type, "line")) {
- break_iterator =
- icu::BreakIterator::createLineInstance(icu_locale, status);
- } else {
- return v8::ThrowException(v8::Exception::SyntaxError(
- v8::String::New("Invalid iterator type.")));
- }
-
- if (U_FAILURE(status)) {
- delete break_iterator;
- return v8::ThrowException(v8::Exception::Error(
- v8::String::New("Failed to create break iterator.")));
- }
-
- if (break_iterator_template_.IsEmpty()) {
- v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New());
-
- raw_template->SetClassName(v8::String::New("v8Locale.v8BreakIterator"));
-
- // Define internal field count on instance template.
- v8::Local<v8::ObjectTemplate> object_template =
- raw_template->InstanceTemplate();
-
- // Set aside internal fields for icu break iterator and adopted text.
- object_template->SetInternalFieldCount(2);
-
- // Define all of the prototype methods on prototype template.
- v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate();
- proto->Set(v8::String::New("adoptText"),
- v8::FunctionTemplate::New(BreakIteratorAdoptText));
- proto->Set(v8::String::New("first"),
- v8::FunctionTemplate::New(BreakIteratorFirst));
- proto->Set(v8::String::New("next"),
- v8::FunctionTemplate::New(BreakIteratorNext));
- proto->Set(v8::String::New("current"),
- v8::FunctionTemplate::New(BreakIteratorCurrent));
- proto->Set(v8::String::New("breakType"),
- v8::FunctionTemplate::New(BreakIteratorBreakType));
-
- break_iterator_template_ =
- v8::Persistent<v8::FunctionTemplate>::New(raw_template);
- }
-
- // Create an empty object wrapper.
- v8::Local<v8::Object> local_object =
- break_iterator_template_->GetFunction()->NewInstance();
- v8::Persistent<v8::Object> wrapper =
- v8::Persistent<v8::Object>::New(local_object);
-
- // Set break iterator as internal field of the resulting JS object.
- wrapper->SetPointerInInternalField(0, break_iterator);
- // Make sure that the pointer to adopted text is NULL.
- wrapper->SetPointerInInternalField(1, NULL);
-
- // Make object handle weak so we can delete iterator once GC kicks in.
- wrapper.MakeWeak(NULL, DeleteBreakIterator);
-
- return wrapper;
-}
-
-} } // namespace v8::internal
diff --git a/src/extensions/experimental/break-iterator.h b/src/extensions/experimental/break-iterator.h
deleted file mode 100644
index 73b9bbd..0000000
--- a/src/extensions/experimental/break-iterator.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_
-#define V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_
-
-#include "include/v8.h"
-
-#include "unicode/uversion.h"
-
-namespace U_ICU_NAMESPACE {
-class BreakIterator;
-class UnicodeString;
-}
-
-namespace v8 {
-namespace internal {
-
-class BreakIterator {
- public:
- static v8::Handle<v8::Value> JSBreakIterator(const v8::Arguments& args);
-
- // Helper methods for various bindings.
-
- // Unpacks break iterator object from corresponding JavaScript object.
- static icu::BreakIterator* UnpackBreakIterator(v8::Handle<v8::Object> obj);
-
- // Deletes the old value and sets the adopted text in
- // corresponding JavaScript object.
- static icu::UnicodeString* ResetAdoptedText(v8::Handle<v8::Object> obj,
- v8::Handle<v8::Value> text_value);
-
- // Release memory we allocated for the BreakIterator once the JS object that
- // holds the pointer gets garbage collected.
- static void DeleteBreakIterator(v8::Persistent<v8::Value> object,
- void* param);
-
- // Assigns new text to the iterator.
- static v8::Handle<v8::Value> BreakIteratorAdoptText(
- const v8::Arguments& args);
-
- // Moves iterator to the beginning of the string and returns new position.
- static v8::Handle<v8::Value> BreakIteratorFirst(const v8::Arguments& args);
-
- // Moves iterator to the next position and returns it.
- static v8::Handle<v8::Value> BreakIteratorNext(const v8::Arguments& args);
-
- // Returns current iterator's current position.
- static v8::Handle<v8::Value> BreakIteratorCurrent(
- const v8::Arguments& args);
-
- // Returns type of the item from current position.
- // This call is only valid for word break iterators. Others just return 0.
- static v8::Handle<v8::Value> BreakIteratorBreakType(
- const v8::Arguments& args);
-
- private:
- BreakIterator() {}
-
- static v8::Persistent<v8::FunctionTemplate> break_iterator_template_;
-};
-
-} } // namespace v8::internal
-
-#endif // V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_
diff --git a/src/extensions/experimental/collator.cc b/src/extensions/experimental/collator.cc
deleted file mode 100644
index 5cf2192..0000000
--- a/src/extensions/experimental/collator.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/extensions/experimental/collator.h"
-
-#include "unicode/coll.h"
-#include "unicode/locid.h"
-#include "unicode/ucol.h"
-
-namespace v8 {
-namespace internal {
-
-v8::Persistent<v8::FunctionTemplate> Collator::collator_template_;
-
-icu::Collator* Collator::UnpackCollator(v8::Handle<v8::Object> obj) {
- if (collator_template_->HasInstance(obj)) {
- return static_cast<icu::Collator*>(obj->GetPointerFromInternalField(0));
- }
-
- return NULL;
-}
-
-void Collator::DeleteCollator(v8::Persistent<v8::Value> object, void* param) {
- v8::Persistent<v8::Object> persistent_object =
- v8::Persistent<v8::Object>::Cast(object);
-
- // First delete the hidden C++ object.
- // Unpacking should never return NULL here. That would only happen if
- // this method is used as the weak callback for persistent handles not
- // pointing to a collator.
- delete UnpackCollator(persistent_object);
-
- // Then dispose of the persistent handle to JS object.
- persistent_object.Dispose();
-}
-
-// Throws a JavaScript exception.
-static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
- // Returns undefined, and schedules an exception to be thrown.
- return v8::ThrowException(v8::Exception::Error(
- v8::String::New("Collator method called on an object "
- "that is not a Collator.")));
-}
-
-// Extract a boolean option named in |option| and set it to |result|.
-// Return true if it's specified. Otherwise, return false.
-static bool ExtractBooleanOption(const v8::Local<v8::Object>& options,
- const char* option,
- bool* result) {
- v8::HandleScope handle_scope;
- v8::TryCatch try_catch;
- v8::Handle<v8::Value> value = options->Get(v8::String::New(option));
- if (try_catch.HasCaught()) {
- return false;
- }
- // No need to check if |value| is empty because it's taken care of
- // by TryCatch above.
- if (!value->IsUndefined() && !value->IsNull()) {
- if (value->IsBoolean()) {
- *result = value->BooleanValue();
- return true;
- }
- }
- return false;
-}
-
-// When there's an ICU error, throw a JavaScript error with |message|.
-static v8::Handle<v8::Value> ThrowExceptionForICUError(const char* message) {
- return v8::ThrowException(v8::Exception::Error(v8::String::New(message)));
-}
-
-v8::Handle<v8::Value> Collator::CollatorCompare(const v8::Arguments& args) {
- if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
- return v8::ThrowException(v8::Exception::SyntaxError(
- v8::String::New("Two string arguments are required.")));
- }
-
- icu::Collator* collator = UnpackCollator(args.Holder());
- if (!collator) {
- return ThrowUnexpectedObjectError();
- }
-
- v8::String::Value string_value1(args[0]);
- v8::String::Value string_value2(args[1]);
- const UChar* string1 = reinterpret_cast<const UChar*>(*string_value1);
- const UChar* string2 = reinterpret_cast<const UChar*>(*string_value2);
- UErrorCode status = U_ZERO_ERROR;
- UCollationResult result = collator->compare(
- string1, string_value1.length(), string2, string_value2.length(), status);
-
- if (U_FAILURE(status)) {
- return ThrowExceptionForICUError(
- "Unexpected failure in Collator.compare.");
- }
-
- return v8::Int32::New(result);
-}
-
-v8::Handle<v8::Value> Collator::JSCollator(const v8::Arguments& args) {
- v8::HandleScope handle_scope;
-
- if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsObject()) {
- return v8::ThrowException(v8::Exception::SyntaxError(
- v8::String::New("Locale and collation options are required.")));
- }
-
- v8::String::AsciiValue locale(args[0]);
- icu::Locale icu_locale(*locale);
-
- icu::Collator* collator = NULL;
- UErrorCode status = U_ZERO_ERROR;
- collator = icu::Collator::createInstance(icu_locale, status);
-
- if (U_FAILURE(status)) {
- delete collator;
- return ThrowExceptionForICUError("Failed to create collator.");
- }
-
- v8::Local<v8::Object> options(args[1]->ToObject());
-
- // Below, we change collation options that are explicitly specified
- // by a caller in JavaScript. Otherwise, we don't touch because
- // we don't want to change the locale-dependent default value.
- // The three options below are very likely to have the same default
- // across locales, but I haven't checked them all. Others we may add
- // in the future have certainly locale-dependent default (e.g.
- // caseFirst is upperFirst for Danish while is off for most other locales).
-
- bool ignore_case, ignore_accents, numeric;
-
- if (ExtractBooleanOption(options, "ignoreCase", &ignore_case)) {
- // We need to explicitly set the level to secondary to get case ignored.
- // The default L3 ignores UCOL_CASE_LEVEL == UCOL_OFF !
- if (ignore_case) {
- collator->setStrength(icu::Collator::SECONDARY);
- }
- collator->setAttribute(UCOL_CASE_LEVEL, ignore_case ? UCOL_OFF : UCOL_ON,
- status);
- if (U_FAILURE(status)) {
- delete collator;
- return ThrowExceptionForICUError("Failed to set ignoreCase.");
- }
- }
-
- // Accents are taken into account with strength secondary or higher.
- if (ExtractBooleanOption(options, "ignoreAccents", &ignore_accents)) {
- if (!ignore_accents) {
- collator->setStrength(icu::Collator::SECONDARY);
- } else {
- collator->setStrength(icu::Collator::PRIMARY);
- }
- }
-
- if (ExtractBooleanOption(options, "numeric", &numeric)) {
- collator->setAttribute(UCOL_NUMERIC_COLLATION,
- numeric ? UCOL_ON : UCOL_OFF, status);
- if (U_FAILURE(status)) {
- delete collator;
- return ThrowExceptionForICUError("Failed to set numeric sort option.");
- }
- }
-
- if (collator_template_.IsEmpty()) {
- v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New());
- raw_template->SetClassName(v8::String::New("v8Locale.Collator"));
-
- // Define internal field count on instance template.
- v8::Local<v8::ObjectTemplate> object_template =
- raw_template->InstanceTemplate();
-
- // Set aside internal fields for icu collator.
- object_template->SetInternalFieldCount(1);
-
- // Define all of the prototype methods on prototype template.
- v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate();
- proto->Set(v8::String::New("compare"),
- v8::FunctionTemplate::New(CollatorCompare));
-
- collator_template_ =
- v8::Persistent<v8::FunctionTemplate>::New(raw_template);
- }
-
- // Create an empty object wrapper.
- v8::Local<v8::Object> local_object =
- collator_template_->GetFunction()->NewInstance();
- v8::Persistent<v8::Object> wrapper =
- v8::Persistent<v8::Object>::New(local_object);
-
- // Set collator as internal field of the resulting JS object.
- wrapper->SetPointerInInternalField(0, collator);
-
- // Make object handle weak so we can delete iterator once GC kicks in.
- wrapper.MakeWeak(NULL, DeleteCollator);
-
- return wrapper;
-}
-
-} } // namespace v8::internal
diff --git a/src/extensions/experimental/collator.h b/src/extensions/experimental/collator.h
deleted file mode 100644
index ca7e4dc..0000000
--- a/src/extensions/experimental/collator.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_EXTENSIONS_EXPERIMENTAL_COLLATOR_H
-#define V8_EXTENSIONS_EXPERIMENTAL_COLLATOR_H_
-
-#include "include/v8.h"
-
-#include "unicode/uversion.h"
-
-namespace U_ICU_NAMESPACE {
-class Collator;
-class UnicodeString;
-}
-
-namespace v8 {
-namespace internal {
-
-class Collator {
- public:
- static v8::Handle<v8::Value> JSCollator(const v8::Arguments& args);
-
- // Helper methods for various bindings.
-
- // Unpacks collator object from corresponding JavaScript object.
- static icu::Collator* UnpackCollator(v8::Handle<v8::Object> obj);
-
- // Release memory we allocated for the Collator once the JS object that
- // holds the pointer gets garbage collected.
- static void DeleteCollator(v8::Persistent<v8::Value> object, void* param);
-
- // Compare two strings and returns -1, 0 and 1 depending on
- // whether string1 is smaller than, equal to or larger than string2.
- static v8::Handle<v8::Value> CollatorCompare(const v8::Arguments& args);
-
- private:
- Collator() {}
-
- static v8::Persistent<v8::FunctionTemplate> collator_template_;
-};
-
-} } // namespace v8::internal
-
-#endif // V8_EXTENSIONS_EXPERIMENTAL_COLLATOR
diff --git a/src/extensions/experimental/datetime-format.cc b/src/extensions/experimental/datetime-format.cc
deleted file mode 100644
index 94a29ac..0000000
--- a/src/extensions/experimental/datetime-format.cc
+++ /dev/null
@@ -1,384 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/extensions/experimental/datetime-format.h"
-
-#include <string.h>
-
-#include "src/extensions/experimental/i18n-utils.h"
-#include "unicode/dtfmtsym.h"
-#include "unicode/dtptngen.h"
-#include "unicode/locid.h"
-#include "unicode/smpdtfmt.h"
-
-namespace v8 {
-namespace internal {
-
-v8::Persistent<v8::FunctionTemplate> DateTimeFormat::datetime_format_template_;
-
-static icu::DateFormat* CreateDateTimeFormat(v8::Handle<v8::String>,
- v8::Handle<v8::Object>);
-static v8::Handle<v8::Value> GetSymbols(
- const v8::Arguments&,
- const icu::UnicodeString*, int32_t,
- const icu::UnicodeString*, int32_t,
- const icu::UnicodeString*, int32_t);
-static v8::Handle<v8::Value> ThrowUnexpectedObjectError();
-static icu::DateFormat::EStyle GetDateTimeStyle(const icu::UnicodeString&);
-
-icu::SimpleDateFormat* DateTimeFormat::UnpackDateTimeFormat(
- v8::Handle<v8::Object> obj) {
- if (datetime_format_template_->HasInstance(obj)) {
- return static_cast<icu::SimpleDateFormat*>(
- obj->GetPointerFromInternalField(0));
- }
-
- return NULL;
-}
-
-void DateTimeFormat::DeleteDateTimeFormat(v8::Persistent<v8::Value> object,
- void* param) {
- v8::Persistent<v8::Object> persistent_object =
- v8::Persistent<v8::Object>::Cast(object);
-
- // First delete the hidden C++ object.
- // Unpacking should never return NULL here. That would only happen if
- // this method is used as the weak callback for persistent handles not
- // pointing to a date time formatter.
- delete UnpackDateTimeFormat(persistent_object);
-
- // Then dispose of the persistent handle to JS object.
- persistent_object.Dispose();
-}
-
-v8::Handle<v8::Value> DateTimeFormat::Format(const v8::Arguments& args) {
- v8::HandleScope handle_scope;
-
- double millis = 0.0;
- if (args.Length() != 1 || !args[0]->IsDate()) {
- // Create a new date.
- v8::TryCatch try_catch;
- v8::Local<v8::Script> date_script =
- v8::Script::Compile(v8::String::New("eval('new Date()')"));
- millis = date_script->Run()->NumberValue();
- if (try_catch.HasCaught()) {
- return try_catch.ReThrow();
- }
- } else {
- millis = v8::Date::Cast(*args[0])->NumberValue();
- }
-
- icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder());
- if (!date_format) {
- return ThrowUnexpectedObjectError();
- }
-
- icu::UnicodeString result;
- date_format->format(millis, result);
-
- return v8::String::New(
- reinterpret_cast<const uint16_t*>(result.getBuffer()), result.length());
-}
-
-v8::Handle<v8::Value> DateTimeFormat::GetMonths(const v8::Arguments& args) {
- icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder());
- if (!date_format) {
- return ThrowUnexpectedObjectError();
- }
-
- const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols();
-
- int32_t narrow_count;
- const icu::UnicodeString* narrow = symbols->getMonths(
- narrow_count,
- icu::DateFormatSymbols::STANDALONE,
- icu::DateFormatSymbols::NARROW);
- int32_t abbrev_count;
- const icu::UnicodeString* abbrev = symbols->getMonths(
- abbrev_count,
- icu::DateFormatSymbols::STANDALONE,
- icu::DateFormatSymbols::ABBREVIATED);
- int32_t wide_count;
- const icu::UnicodeString* wide = symbols->getMonths(
- wide_count,
- icu::DateFormatSymbols::STANDALONE,
- icu::DateFormatSymbols::WIDE);
-
- return GetSymbols(
- args, narrow, narrow_count, abbrev, abbrev_count, wide, wide_count);
-}
-
-v8::Handle<v8::Value> DateTimeFormat::GetWeekdays(const v8::Arguments& args) {
- icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder());
- if (!date_format) {
- return ThrowUnexpectedObjectError();
- }
-
- const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols();
-
- int32_t narrow_count;
- const icu::UnicodeString* narrow = symbols->getWeekdays(
- narrow_count,
- icu::DateFormatSymbols::STANDALONE,
- icu::DateFormatSymbols::NARROW);
- int32_t abbrev_count;
- const icu::UnicodeString* abbrev = symbols->getWeekdays(
- abbrev_count,
- icu::DateFormatSymbols::STANDALONE,
- icu::DateFormatSymbols::ABBREVIATED);
- int32_t wide_count;
- const icu::UnicodeString* wide = symbols->getWeekdays(
- wide_count,
- icu::DateFormatSymbols::STANDALONE,
- icu::DateFormatSymbols::WIDE);
-
- // getXXXWeekdays always returns 8 elements - ICU stable API.
- // We can't use ASSERT_EQ(8, narrow_count) because ASSERT is internal to v8.
- if (narrow_count != 8 || abbrev_count != 8 || wide_count != 8) {
- return v8::ThrowException(v8::Exception::Error(
- v8::String::New("Failed to get weekday information.")));
- }
-
- // ICU documentation says we should ignore element 0 of the returned array.
- return GetSymbols(args, narrow + 1, narrow_count - 1, abbrev + 1,
- abbrev_count -1 , wide + 1, wide_count - 1);
-}
-
-v8::Handle<v8::Value> DateTimeFormat::GetEras(const v8::Arguments& args) {
- icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder());
- if (!date_format) {
- return ThrowUnexpectedObjectError();
- }
-
- const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols();
-
- int32_t narrow_count;
- const icu::UnicodeString* narrow = symbols->getNarrowEras(narrow_count);
- int32_t abbrev_count;
- const icu::UnicodeString* abbrev = symbols->getEras(abbrev_count);
- int32_t wide_count;
- const icu::UnicodeString* wide = symbols->getEraNames(wide_count);
-
- return GetSymbols(
- args, narrow, narrow_count, abbrev, abbrev_count, wide, wide_count);
-}
-
-v8::Handle<v8::Value> DateTimeFormat::GetAmPm(const v8::Arguments& args) {
- icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder());
- if (!date_format) {
- return ThrowUnexpectedObjectError();
- }
-
- const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols();
-
- // In this case narrow == abbreviated == wide
- int32_t count;
- const icu::UnicodeString* wide = symbols->getAmPmStrings(count);
-
- return GetSymbols(args, wide, count, wide, count, wide, count);
-}
-
-v8::Handle<v8::Value> DateTimeFormat::JSDateTimeFormat(
- const v8::Arguments& args) {
- v8::HandleScope handle_scope;
-
- if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsObject()) {
- return v8::ThrowException(v8::Exception::SyntaxError(
- v8::String::New("Locale and date/time options are required.")));
- }
-
- icu::SimpleDateFormat* date_format = static_cast<icu::SimpleDateFormat*>(
- CreateDateTimeFormat(args[0]->ToString(), args[1]->ToObject()));
-
- if (datetime_format_template_.IsEmpty()) {
- v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New());
-
- raw_template->SetClassName(v8::String::New("v8Locale.DateTimeFormat"));
-
- // Define internal field count on instance template.
- v8::Local<v8::ObjectTemplate> object_template =
- raw_template->InstanceTemplate();
-
- // Set aside internal field for icu date time formatter.
- object_template->SetInternalFieldCount(1);
-
- // Define all of the prototype methods on prototype template.
- v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate();
- proto->Set(v8::String::New("format"),
- v8::FunctionTemplate::New(Format));
- proto->Set(v8::String::New("getMonths"),
- v8::FunctionTemplate::New(GetMonths));
- proto->Set(v8::String::New("getWeekdays"),
- v8::FunctionTemplate::New(GetWeekdays));
- proto->Set(v8::String::New("getEras"),
- v8::FunctionTemplate::New(GetEras));
- proto->Set(v8::String::New("getAmPm"),
- v8::FunctionTemplate::New(GetAmPm));
-
- datetime_format_template_ =
- v8::Persistent<v8::FunctionTemplate>::New(raw_template);
- }
-
- // Create an empty object wrapper.
- v8::Local<v8::Object> local_object =
- datetime_format_template_->GetFunction()->NewInstance();
- v8::Persistent<v8::Object> wrapper =
- v8::Persistent<v8::Object>::New(local_object);
-
- // Set date time formatter as internal field of the resulting JS object.
- wrapper->SetPointerInInternalField(0, date_format);
-
- // Set resolved pattern in options.pattern.
- icu::UnicodeString pattern;
- date_format->toPattern(pattern);
- v8::Local<v8::Object> options = v8::Object::New();
- options->Set(v8::String::New("pattern"),
- v8::String::New(reinterpret_cast<const uint16_t*>(
- pattern.getBuffer()), pattern.length()));
- wrapper->Set(v8::String::New("options"), options);
-
- // Make object handle weak so we can delete iterator once GC kicks in.
- wrapper.MakeWeak(NULL, DeleteDateTimeFormat);
-
- return wrapper;
-}
-
-// Returns SimpleDateFormat.
-static icu::DateFormat* CreateDateTimeFormat(
- v8::Handle<v8::String> locale, v8::Handle<v8::Object> settings) {
- v8::HandleScope handle_scope;
-
- v8::String::AsciiValue ascii_locale(locale);
- icu::Locale icu_locale(*ascii_locale);
-
- // Make formatter from skeleton.
- icu::SimpleDateFormat* date_format = NULL;
- UErrorCode status = U_ZERO_ERROR;
- icu::UnicodeString skeleton;
- if (I18NUtils::ExtractStringSetting(settings, "skeleton", &skeleton)) {
- v8::Local<icu::DateTimePatternGenerator> generator(
- icu::DateTimePatternGenerator::createInstance(icu_locale, status));
- icu::UnicodeString pattern =
- generator->getBestPattern(skeleton, status);
-
- date_format = new icu::SimpleDateFormat(pattern, icu_locale, status);
- if (U_SUCCESS(status)) {
- return date_format;
- } else {
- delete date_format;
- }
- }
-
- // Extract date style and time style from settings.
- icu::UnicodeString date_style;
- icu::DateFormat::EStyle icu_date_style = icu::DateFormat::kNone;
- if (I18NUtils::ExtractStringSetting(settings, "dateStyle", &date_style)) {
- icu_date_style = GetDateTimeStyle(date_style);
- }
-
- icu::UnicodeString time_style;
- icu::DateFormat::EStyle icu_time_style = icu::DateFormat::kNone;
- if (I18NUtils::ExtractStringSetting(settings, "timeStyle", &time_style)) {
- icu_time_style = GetDateTimeStyle(time_style);
- }
-
- // Try all combinations of date/time styles.
- if (icu_date_style == icu::DateFormat::kNone &&
- icu_time_style == icu::DateFormat::kNone) {
- // Return default short date, short
- return icu::DateFormat::createDateTimeInstance(
- icu::DateFormat::kShort, icu::DateFormat::kShort, icu_locale);
- } else if (icu_date_style != icu::DateFormat::kNone &&
- icu_time_style != icu::DateFormat::kNone) {
- return icu::DateFormat::createDateTimeInstance(
- icu_date_style, icu_time_style, icu_locale);
- } else if (icu_date_style != icu::DateFormat::kNone) {
- return icu::DateFormat::createDateInstance(icu_date_style, icu_locale);
- } else {
- // icu_time_style != icu::DateFormat::kNone
- return icu::DateFormat::createTimeInstance(icu_time_style, icu_locale);
- }
-}
-
-// Creates a v8::Array of narrow, abbrev or wide symbols.
-static v8::Handle<v8::Value> GetSymbols(const v8::Arguments& args,
- const icu::UnicodeString* narrow,
- int32_t narrow_count,
- const icu::UnicodeString* abbrev,
- int32_t abbrev_count,
- const icu::UnicodeString* wide,
- int32_t wide_count) {
- v8::HandleScope handle_scope;
-
- // Make wide width default.
- const icu::UnicodeString* result = wide;
- int32_t count = wide_count;
-
- if (args.Length() == 1 && args[0]->IsString()) {
- v8::String::AsciiValue ascii_value(args[0]);
- if (strcmp(*ascii_value, "abbreviated") == 0) {
- result = abbrev;
- count = abbrev_count;
- } else if (strcmp(*ascii_value, "narrow") == 0) {
- result = narrow;
- count = narrow_count;
- }
- }
-
- v8::Handle<v8::Array> symbols = v8::Array::New();
- for (int32_t i = 0; i < count; ++i) {
- symbols->Set(i, v8::String::New(
- reinterpret_cast<const uint16_t*>(result[i].getBuffer()),
- result[i].length()));
- }
-
- return handle_scope.Close(symbols);
-}
-
-// Throws a JavaScript exception.
-static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
- // Returns undefined, and schedules an exception to be thrown.
- return v8::ThrowException(v8::Exception::Error(
- v8::String::New("DateTimeFormat method called on an object "
- "that is not a DateTimeFormat.")));
-}
-
-// Returns icu date/time style.
-static icu::DateFormat::EStyle GetDateTimeStyle(
- const icu::UnicodeString& type) {
- if (type == UNICODE_STRING_SIMPLE("medium")) {
- return icu::DateFormat::kMedium;
- } else if (type == UNICODE_STRING_SIMPLE("long")) {
- return icu::DateFormat::kLong;
- } else if (type == UNICODE_STRING_SIMPLE("full")) {
- return icu::DateFormat::kFull;
- }
-
- return icu::DateFormat::kShort;
-}
-
-} } // namespace v8::internal
diff --git a/src/extensions/experimental/datetime-format.h b/src/extensions/experimental/datetime-format.h
deleted file mode 100644
index a6a228c..0000000
--- a/src/extensions/experimental/datetime-format.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_EXTENSIONS_EXPERIMENTAL_DATETIME_FORMAT_H_
-#define V8_EXTENSIONS_EXPERIMENTAL_DATETIME_FORMAT_H_
-
-#include "include/v8.h"
-
-#include "unicode/uversion.h"
-
-namespace U_ICU_NAMESPACE {
-class SimpleDateFormat;
-}
-
-namespace v8 {
-namespace internal {
-
-class DateTimeFormat {
- public:
- static v8::Handle<v8::Value> JSDateTimeFormat(const v8::Arguments& args);
-
- // Helper methods for various bindings.
-
- // Unpacks date format object from corresponding JavaScript object.
- static icu::SimpleDateFormat* UnpackDateTimeFormat(
- v8::Handle<v8::Object> obj);
-
- // Release memory we allocated for the DateFormat once the JS object that
- // holds the pointer gets garbage collected.
- static void DeleteDateTimeFormat(v8::Persistent<v8::Value> object,
- void* param);
-
- // Formats date and returns corresponding string.
- static v8::Handle<v8::Value> Format(const v8::Arguments& args);
-
- // All date time symbol methods below return stand-alone names in
- // either narrow, abbreviated or wide width.
-
- // Get list of months.
- static v8::Handle<v8::Value> GetMonths(const v8::Arguments& args);
-
- // Get list of weekdays.
- static v8::Handle<v8::Value> GetWeekdays(const v8::Arguments& args);
-
- // Get list of eras.
- static v8::Handle<v8::Value> GetEras(const v8::Arguments& args);
-
- // Get list of day periods.
- static v8::Handle<v8::Value> GetAmPm(const v8::Arguments& args);
-
- private:
- DateTimeFormat();
-
- static v8::Persistent<v8::FunctionTemplate> datetime_format_template_;
-};
-
-} } // namespace v8::internal
-
-#endif // V8_EXTENSIONS_EXPERIMENTAL_DATETIME_FORMAT_H_
diff --git a/src/extensions/experimental/experimental.gyp b/src/extensions/experimental/experimental.gyp
deleted file mode 100644
index 24fb683..0000000
--- a/src/extensions/experimental/experimental.gyp
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2011 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:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following
-# disclaimer in the documentation and/or other materials provided
-# with the distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived
-# from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-{
- 'variables': {
- # TODO(cira): Find out how to pass this value for arbitrary embedder.
- # Chromium sets it in common.gypi and does force include of that file for
- # all sub projects.
- 'icu_src_dir%': '../../../../third_party/icu',
- },
- 'targets': [
- {
- 'target_name': 'i18n_api',
- 'type': 'static_library',
- 'sources': [
- 'break-iterator.cc',
- 'break-iterator.h',
- 'collator.cc',
- 'collator.h',
- 'datetime-format.cc',
- 'datetime-format.h',
- 'i18n-extension.cc',
- 'i18n-extension.h',
- 'i18n-locale.cc',
- 'i18n-locale.h',
- 'i18n-natives.h',
- 'i18n-utils.cc',
- 'i18n-utils.h',
- 'language-matcher.cc',
- 'language-matcher.h',
- 'number-format.cc',
- 'number-format.h',
- '<(SHARED_INTERMEDIATE_DIR)/i18n-js.cc',
- ],
- 'include_dirs': [
- '<(icu_src_dir)/public/common',
- # v8/ is root for all includes.
- '../../..'
- ],
- 'dependencies': [
- '<(icu_src_dir)/icu.gyp:*',
- 'js2c_i18n#host',
- '../../../tools/gyp/v8.gyp:v8',
- ],
- 'direct_dependent_settings': {
- # Adds -Iv8 for embedders.
- 'include_dirs': [
- '../../..'
- ],
- },
- },
- {
- 'target_name': 'js2c_i18n',
- 'type': 'none',
- 'toolsets': ['host'],
- 'variables': {
- 'js_files': [
- 'i18n.js'
- ],
- },
- 'actions': [
- {
- 'action_name': 'js2c_i18n',
- 'inputs': [
- 'i18n-js2c.py',
- '<@(js_files)',
- ],
- 'outputs': [
- '<(SHARED_INTERMEDIATE_DIR)/i18n-js.cc',
- ],
- 'action': [
- 'python',
- 'i18n-js2c.py',
- '<@(_outputs)',
- '<@(js_files)'
- ],
- },
- ],
- },
- ], # targets
-}
diff --git a/src/extensions/experimental/i18n-extension.cc b/src/extensions/experimental/i18n-extension.cc
deleted file mode 100644
index c5afcf0..0000000
--- a/src/extensions/experimental/i18n-extension.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/extensions/experimental/i18n-extension.h"
-
-#include "src/extensions/experimental/break-iterator.h"
-#include "src/extensions/experimental/collator.h"
-#include "src/extensions/experimental/datetime-format.h"
-#include "src/extensions/experimental/i18n-locale.h"
-#include "src/extensions/experimental/i18n-natives.h"
-#include "src/extensions/experimental/number-format.h"
-
-namespace v8 {
-namespace internal {
-
-I18NExtension* I18NExtension::extension_ = NULL;
-
-I18NExtension::I18NExtension()
- : v8::Extension("v8/i18n", I18Natives::GetScriptSource()) {
-}
-
-v8::Handle<v8::FunctionTemplate> I18NExtension::GetNativeFunction(
- v8::Handle<v8::String> name) {
- if (name->Equals(v8::String::New("NativeJSLocale"))) {
- return v8::FunctionTemplate::New(I18NLocale::JSLocale);
- } else if (name->Equals(v8::String::New("NativeJSBreakIterator"))) {
- return v8::FunctionTemplate::New(BreakIterator::JSBreakIterator);
- } else if (name->Equals(v8::String::New("NativeJSCollator"))) {
- return v8::FunctionTemplate::New(Collator::JSCollator);
- } else if (name->Equals(v8::String::New("NativeJSDateTimeFormat"))) {
- return v8::FunctionTemplate::New(DateTimeFormat::JSDateTimeFormat);
- } else if (name->Equals(v8::String::New("NativeJSNumberFormat"))) {
- return v8::FunctionTemplate::New(NumberFormat::JSNumberFormat);
- }
-
- return v8::Handle<v8::FunctionTemplate>();
-}
-
-I18NExtension* I18NExtension::get() {
- if (!extension_) {
- extension_ = new I18NExtension();
- }
- return extension_;
-}
-
-void I18NExtension::Register() {
- static v8::DeclareExtension i18n_extension_declaration(I18NExtension::get());
-}
-
-} } // namespace v8::internal
diff --git a/src/extensions/experimental/i18n-extension.h b/src/extensions/experimental/i18n-extension.h
deleted file mode 100644
index 5401f25..0000000
--- a/src/extensions/experimental/i18n-extension.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_EXTENSIONS_EXPERIMENTAL_I18N_EXTENSION_H_
-#define V8_EXTENSIONS_EXPERIMENTAL_I18N_EXTENSION_H_
-
-#include "include/v8.h"
-
-namespace v8 {
-namespace internal {
-
-
-class I18NExtension : public v8::Extension {
- public:
- I18NExtension();
-
- virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
- v8::Handle<v8::String> name);
-
- // V8 code prefers Register, while Chrome and WebKit use get kind of methods.
- static void Register();
- static I18NExtension* get();
-
- private:
- static I18NExtension* extension_;
-};
-
-} } // namespace v8::internal
-
-#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_EXTENSION_H_
diff --git a/src/extensions/experimental/i18n-js2c.py b/src/extensions/experimental/i18n-js2c.py
deleted file mode 100644
index 9c3128b..0000000
--- a/src/extensions/experimental/i18n-js2c.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2011 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:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following
-# disclaimer in the documentation and/or other materials provided
-# with the distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived
-# from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# This is a utility for converting I18N JavaScript source code into C-style
-# char arrays. It is used for embedded JavaScript code in the V8
-# library.
-# This is a pared down copy of v8/tools/js2c.py that avoids use of
-# v8/src/natives.h and produces different cc template.
-
-import os, re, sys, string
-
-
-def ToCArray(lines):
- result = []
- for chr in lines:
- value = ord(chr)
- assert value < 128
- result.append(str(value))
- result.append("0")
- return ", ".join(result)
-
-
-def RemoveCommentsAndTrailingWhitespace(lines):
- lines = re.sub(r'//.*\n', '\n', lines) # end-of-line comments
- lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments.
- lines = re.sub(r'\s+\n+', '\n', lines) # trailing whitespace
- return lines
-
-
-def ReadFile(filename):
- file = open(filename, "rt")
- try:
- lines = file.read()
- finally:
- file.close()
- return lines
-
-
-EVAL_PATTERN = re.compile(r'\beval\s*\(');
-WITH_PATTERN = re.compile(r'\bwith\s*\(');
-
-
-def Validate(lines, file):
- lines = RemoveCommentsAndTrailingWhitespace(lines)
- # Because of simplified context setup, eval and with is not
- # allowed in the natives files.
- eval_match = EVAL_PATTERN.search(lines)
- if eval_match:
- raise ("Eval disallowed in natives: %s" % file)
- with_match = WITH_PATTERN.search(lines)
- if with_match:
- raise ("With statements disallowed in natives: %s" % file)
-
-
-HEADER_TEMPLATE = """\
-// Copyright 2011 Google Inc. All Rights Reserved.
-
-// This file was generated from .js source files by gyp. If you
-// want to make changes to this file you should either change the
-// javascript source files or the i18n-js2c.py script.
-
-#include "src/extensions/experimental/i18n-natives.h"
-
-namespace v8 {
-namespace internal {
-
-// static
-const char* I18Natives::GetScriptSource() {
- // JavaScript source gets injected here.
- static const char i18n_source[] = {%s};
-
- return i18n_source;
-}
-
-} // internal
-} // v8
-"""
-
-
-def JS2C(source, target):
- filename = str(source)
-
- lines = ReadFile(filename)
- Validate(lines, filename)
- data = ToCArray(lines)
-
- # Emit result
- output = open(target, "w")
- output.write(HEADER_TEMPLATE % data)
- output.close()
-
-
-def main():
- target = sys.argv[1]
- source = sys.argv[2]
- JS2C(source, target)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/extensions/experimental/i18n-locale.cc b/src/extensions/experimental/i18n-locale.cc
deleted file mode 100644
index 46a5f87..0000000
--- a/src/extensions/experimental/i18n-locale.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/extensions/experimental/i18n-locale.h"
-
-#include "src/extensions/experimental/i18n-utils.h"
-#include "src/extensions/experimental/language-matcher.h"
-#include "unicode/locid.h"
-#include "unicode/uloc.h"
-
-namespace v8 {
-namespace internal {
-
-const char* const I18NLocale::kLocaleID = "localeID";
-const char* const I18NLocale::kRegionID = "regionID";
-const char* const I18NLocale::kICULocaleID = "icuLocaleID";
-
-v8::Handle<v8::Value> I18NLocale::JSLocale(const v8::Arguments& args) {
- v8::HandleScope handle_scope;
-
- if (args.Length() != 1 || !args[0]->IsObject()) {
- return v8::Undefined();
- }
-
- v8::Local<v8::Object> settings = args[0]->ToObject();
-
- // Get best match for locale.
- v8::TryCatch try_catch;
- v8::Handle<v8::Value> locale_id = settings->Get(v8::String::New(kLocaleID));
- if (try_catch.HasCaught()) {
- return v8::Undefined();
- }
-
- LocaleIDMatch result;
- if (locale_id->IsArray()) {
- LanguageMatcher::GetBestMatchForPriorityList(
- v8::Handle<v8::Array>::Cast(locale_id), &result);
- } else if (locale_id->IsString()) {
- LanguageMatcher::GetBestMatchForString(locale_id->ToString(), &result);
- } else {
- LanguageMatcher::GetBestMatchForString(v8::String::New(""), &result);
- }
-
- // Get best match for region.
- char region_id[ULOC_COUNTRY_CAPACITY];
- I18NUtils::StrNCopy(region_id, ULOC_COUNTRY_CAPACITY, "");
-
- v8::Handle<v8::Value> region = settings->Get(v8::String::New(kRegionID));
- if (try_catch.HasCaught()) {
- return v8::Undefined();
- }
-
- if (!GetBestMatchForRegionID(result.icu_id, region, region_id)) {
- // Set region id to empty string because region couldn't be inferred.
- I18NUtils::StrNCopy(region_id, ULOC_COUNTRY_CAPACITY, "");
- }
-
- // Build JavaScript object that contains bcp and icu locale ID and region ID.
- v8::Handle<v8::Object> locale = v8::Object::New();
- locale->Set(v8::String::New(kLocaleID), v8::String::New(result.bcp47_id));
- locale->Set(v8::String::New(kICULocaleID), v8::String::New(result.icu_id));
- locale->Set(v8::String::New(kRegionID), v8::String::New(region_id));
-
- return handle_scope.Close(locale);
-}
-
-bool I18NLocale::GetBestMatchForRegionID(
- const char* locale_id, v8::Handle<v8::Value> region_id, char* result) {
- if (region_id->IsString() && region_id->ToString()->Length() != 0) {
- icu::Locale user_locale(
- icu::Locale("und", *v8::String::Utf8Value(region_id->ToString())));
- I18NUtils::StrNCopy(
- result, ULOC_COUNTRY_CAPACITY, user_locale.getCountry());
- return true;
- }
- // Maximize locale_id to infer the region (e.g. expand "de" to "de-Latn-DE"
- // and grab "DE" from the result).
- UErrorCode status = U_ZERO_ERROR;
- char maximized_locale[ULOC_FULLNAME_CAPACITY];
- uloc_addLikelySubtags(
- locale_id, maximized_locale, ULOC_FULLNAME_CAPACITY, &status);
- uloc_getCountry(maximized_locale, result, ULOC_COUNTRY_CAPACITY, &status);
-
- return !U_FAILURE(status);
-}
-
-} } // namespace v8::internal
diff --git a/src/extensions/experimental/i18n-locale.h b/src/extensions/experimental/i18n-locale.h
deleted file mode 100644
index 607818c..0000000
--- a/src/extensions/experimental/i18n-locale.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_EXTENSIONS_EXPERIMENTAL_I18N_LOCALE_H_
-#define V8_EXTENSIONS_EXPERIMENTAL_I18N_LOCALE_H_
-
-#include "include/v8.h"
-
-namespace v8 {
-namespace internal {
-
-class I18NLocale {
- public:
- I18NLocale() {}
-
- // Implementations of window.Locale methods.
- static v8::Handle<v8::Value> JSLocale(const v8::Arguments& args);
-
- // Infers region id given the locale id, or uses user specified region id.
- // Result is canonicalized.
- // Returns status of ICU operation (maximizing locale or get region call).
- static bool GetBestMatchForRegionID(
- const char* locale_id, v8::Handle<v8::Value> regions, char* result);
-
- private:
- // Key name for localeID parameter.
- static const char* const kLocaleID;
- // Key name for regionID parameter.
- static const char* const kRegionID;
- // Key name for the icuLocaleID result.
- static const char* const kICULocaleID;
-};
-
-} } // namespace v8::internal
-
-#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_LOCALE_H_
diff --git a/src/extensions/experimental/i18n-natives.h b/src/extensions/experimental/i18n-natives.h
deleted file mode 100644
index 37362d0..0000000
--- a/src/extensions/experimental/i18n-natives.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_EXTENSIONS_EXPERIMENTAL_I18N_NATIVES_H_
-#define V8_EXTENSIONS_EXPERIMENTAL_I18N_NATIVES_H_
-
-namespace v8 {
-namespace internal {
-
-class I18Natives {
- public:
- // Gets script source from generated file.
- // Source is statically allocated string.
- static const char* GetScriptSource();
-};
-
-} } // namespace v8::internal
-
-#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_NATIVES_H_
diff --git a/src/extensions/experimental/i18n-utils.cc b/src/extensions/experimental/i18n-utils.cc
deleted file mode 100644
index dc2be1a..0000000
--- a/src/extensions/experimental/i18n-utils.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/extensions/experimental/i18n-utils.h"
-
-#include <string.h>
-
-#include "unicode/unistr.h"
-
-namespace v8 {
-namespace internal {
-
-// static
-void I18NUtils::StrNCopy(char* dest, int length, const char* src) {
- if (!dest || !src) return;
-
- strncpy(dest, src, length);
- dest[length - 1] = '\0';
-}
-
-// static
-bool I18NUtils::ExtractStringSetting(const v8::Handle<v8::Object>& settings,
- const char* setting,
- icu::UnicodeString* result) {
- if (!setting || !result) return false;
-
- v8::HandleScope handle_scope;
- v8::TryCatch try_catch;
- v8::Handle<v8::Value> value = settings->Get(v8::String::New(setting));
- if (try_catch.HasCaught()) {
- return false;
- }
- // No need to check if |value| is empty because it's taken care of
- // by TryCatch above.
- if (!value->IsUndefined() && !value->IsNull() && value->IsString()) {
- v8::String::Utf8Value utf8_value(value);
- if (*utf8_value == NULL) return false;
- result->setTo(icu::UnicodeString::fromUTF8(*utf8_value));
- return true;
- }
- return false;
-}
-
-// static
-void I18NUtils::AsciiToUChar(const char* source,
- int32_t source_length,
- UChar* target,
- int32_t target_length) {
- int32_t length =
- source_length < target_length ? source_length : target_length;
-
- if (length <= 0) {
- return;
- }
-
- for (int32_t i = 0; i < length - 1; ++i) {
- target[i] = static_cast<UChar>(source[i]);
- }
-
- target[length - 1] = 0x0u;
-}
-
-} } // namespace v8::internal
diff --git a/src/extensions/experimental/i18n-utils.h b/src/extensions/experimental/i18n-utils.h
deleted file mode 100644
index 7c31528..0000000
--- a/src/extensions/experimental/i18n-utils.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_EXTENSIONS_EXPERIMENTAL_I18N_UTILS_H_
-#define V8_EXTENSIONS_EXPERIMENTAL_I18N_UTILS_H_
-
-#include "include/v8.h"
-
-#include "unicode/uversion.h"
-
-namespace U_ICU_NAMESPACE {
-class UnicodeString;
-}
-
-namespace v8 {
-namespace internal {
-
-class I18NUtils {
- public:
- // Safe string copy. Null terminates the destination. Copies at most
- // (length - 1) bytes.
- // We can't use snprintf since it's not supported on all relevant platforms.
- // We can't use OS::SNPrintF, it's only for internal code.
- static void StrNCopy(char* dest, int length, const char* src);
-
- // Extract a string setting named in |settings| and set it to |result|.
- // Return true if it's specified. Otherwise, return false.
- static bool ExtractStringSetting(const v8::Handle<v8::Object>& settings,
- const char* setting,
- icu::UnicodeString* result);
-
- // Converts ASCII array into UChar array.
- // Target is always \0 terminated.
- static void AsciiToUChar(const char* source,
- int32_t source_length,
- UChar* target,
- int32_t target_length);
-
- private:
- I18NUtils() {}
-};
-
-} } // namespace v8::internal
-
-#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_UTILS_H_
diff --git a/src/extensions/experimental/i18n.js b/src/extensions/experimental/i18n.js
deleted file mode 100644
index 56bcf9e..0000000
--- a/src/extensions/experimental/i18n.js
+++ /dev/null
@@ -1,380 +0,0 @@
-// Copyright 2006-2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// TODO(cira): Rename v8Locale into LocaleInfo once we have stable API.
-/**
- * LocaleInfo class is an aggregate class of all i18n API calls.
- * @param {Object} settings - localeID and regionID to create LocaleInfo from.
- * {Array.<string>|string} settings.localeID -
- * Unicode identifier of the locale.
- * See http://unicode.org/reports/tr35/#BCP_47_Conformance
- * {string} settings.regionID - ISO3166 region ID with addition of
- * invalid, undefined and reserved region codes.
- * @constructor
- */
-v8Locale = function(settings) {
- native function NativeJSLocale();
-
- // Assume user wanted to do v8Locale("sr");
- if (typeof(settings) === "string") {
- settings = {'localeID': settings};
- }
-
- var properties = NativeJSLocale(
- v8Locale.__createSettingsOrDefault(settings, {'localeID': 'root'}));
-
- // Keep the resolved ICU locale ID around to avoid resolving localeID to
- // ICU locale ID every time BreakIterator, Collator and so forth are called.
- this.__icuLocaleID = properties.icuLocaleID;
- this.options = {'localeID': properties.localeID,
- 'regionID': properties.regionID};
-};
-
-/**
- * Clones existing locale with possible overrides for some of the options.
- * @param {!Object} settings - overrides for current locale settings.
- * @returns {Object} - new LocaleInfo object.
- */
-v8Locale.prototype.derive = function(settings) {
- return new v8Locale(
- v8Locale.__createSettingsOrDefault(settings, this.options));
-};
-
-/**
- * v8BreakIterator class implements locale aware segmenatation.
- * It is not part of EcmaScript proposal.
- * @param {Object} locale - locale object to pass to break
- * iterator implementation.
- * @param {string} type - type of segmenatation:
- * - character
- * - word
- * - sentence
- * - line
- * @private
- * @constructor
- */
-v8Locale.v8BreakIterator = function(locale, type) {
- native function NativeJSBreakIterator();
-
- locale = v8Locale.__createLocaleOrDefault(locale);
- // BCP47 ID would work in this case, but we use ICU locale for consistency.
- var iterator = NativeJSBreakIterator(locale.__icuLocaleID, type);
- iterator.type = type;
- return iterator;
-};
-
-/**
- * Type of the break we encountered during previous iteration.
- * @type{Enum}
- */
-v8Locale.v8BreakIterator.BreakType = {
- 'unknown': -1,
- 'none': 0,
- 'number': 100,
- 'word': 200,
- 'kana': 300,
- 'ideo': 400
-};
-
-/**
- * Creates new v8BreakIterator based on current locale.
- * @param {string} - type of segmentation. See constructor.
- * @returns {Object} - new v8BreakIterator object.
- */
-v8Locale.prototype.v8CreateBreakIterator = function(type) {
- return new v8Locale.v8BreakIterator(this, type);
-};
-
-// TODO(jungshik): Set |collator.options| to actually recognized / resolved
-// values.
-/**
- * Collator class implements locale-aware sort.
- * @param {Object} locale - locale object to pass to collator implementation.
- * @param {Object} settings - collation flags:
- * - ignoreCase
- * - ignoreAccents
- * - numeric
- * @private
- * @constructor
- */
-v8Locale.Collator = function(locale, settings) {
- native function NativeJSCollator();
-
- locale = v8Locale.__createLocaleOrDefault(locale);
- var collator = NativeJSCollator(
- locale.__icuLocaleID, v8Locale.__createSettingsOrDefault(settings, {}));
- return collator;
-};
-
-/**
- * Creates new Collator based on current locale.
- * @param {Object} - collation flags. See constructor.
- * @returns {Object} - new Collator object.
- */
-v8Locale.prototype.createCollator = function(settings) {
- return new v8Locale.Collator(this, settings);
-};
-
-/**
- * DateTimeFormat class implements locale-aware date and time formatting.
- * Constructor is not part of public API.
- * @param {Object} locale - locale object to pass to formatter.
- * @param {Object} settings - formatting flags:
- * - skeleton
- * - dateStyle
- * - timeStyle
- * @private
- * @constructor
- */
-v8Locale.__DateTimeFormat = function(locale, settings) {
- native function NativeJSDateTimeFormat();
-
- settings = v8Locale.__createSettingsOrDefault(settings, {});
-
- var cleanSettings = {};
- if (settings.hasOwnProperty('skeleton')) {
- cleanSettings['skeleton'] = settings['skeleton'];
- } else {
- cleanSettings = {};
- if (settings.hasOwnProperty('dateStyle')) {
- var ds = settings['dateStyle'];
- if (!/^(short|medium|long|full)$/.test(ds)) ds = 'short';
- cleanSettings['dateStyle'] = ds;
- } else if (settings.hasOwnProperty('dateType')) {
- // Obsolete. New spec requires dateStyle, but we'll keep this around
- // for current users.
- // TODO(cira): Remove when all internal users switch to dateStyle.
- var dt = settings['dateType'];
- if (!/^(short|medium|long|full)$/.test(dt)) dt = 'short';
- cleanSettings['dateStyle'] = dt;
- }
-
- if (settings.hasOwnProperty('timeStyle')) {
- var ts = settings['timeStyle'];
- if (!/^(short|medium|long|full)$/.test(ts)) ts = 'short';
- cleanSettings['timeStyle'] = ts;
- } else if (settings.hasOwnProperty('timeType')) {
- // TODO(cira): Remove when all internal users switch to timeStyle.
- var tt = settings['timeType'];
- if (!/^(short|medium|long|full)$/.test(tt)) tt = 'short';
- cleanSettings['timeStyle'] = tt;
- }
- }
-
- // Default is to show short date and time.
- if (!cleanSettings.hasOwnProperty('skeleton') &&
- !cleanSettings.hasOwnProperty('dateStyle') &&
- !cleanSettings.hasOwnProperty('timeStyle')) {
- cleanSettings = {'dateStyle': 'short',
- 'timeStyle': 'short'};
- }
-
- locale = v8Locale.__createLocaleOrDefault(locale);
- var formatter = NativeJSDateTimeFormat(locale.__icuLocaleID, cleanSettings);
-
- // NativeJSDateTimeFormat creates formatter.options for us, we just need
- // to append actual settings to it.
- for (key in cleanSettings) {
- formatter.options[key] = cleanSettings[key];
- }
-
- /**
- * Clones existing date time format with possible overrides for some
- * of the options.
- * @param {!Object} overrideSettings - overrides for current format settings.
- * @returns {Object} - new DateTimeFormat object.
- * @public
- */
- formatter.derive = function(overrideSettings) {
- // To remove a setting user can specify undefined as its value. We'll remove
- // it from the map in that case.
- for (var prop in overrideSettings) {
- if (settings.hasOwnProperty(prop) && !overrideSettings[prop]) {
- delete settings[prop];
- }
- }
- return new v8Locale.__DateTimeFormat(
- locale, v8Locale.__createSettingsOrDefault(overrideSettings, settings));
- };
-
- return formatter;
-};
-
-/**
- * Creates new DateTimeFormat based on current locale.
- * @param {Object} - formatting flags. See constructor.
- * @returns {Object} - new DateTimeFormat object.
- */
-v8Locale.prototype.createDateTimeFormat = function(settings) {
- return new v8Locale.__DateTimeFormat(this, settings);
-};
-
-/**
- * NumberFormat class implements locale-aware number formatting.
- * Constructor is not part of public API.
- * @param {Object} locale - locale object to pass to formatter.
- * @param {Object} settings - formatting flags:
- * - skeleton
- * - pattern
- * - style - decimal, currency, percent or scientific
- * - currencyCode - ISO 4217 3-letter currency code
- * @private
- * @constructor
- */
-v8Locale.__NumberFormat = function(locale, settings) {
- native function NativeJSNumberFormat();
-
- settings = v8Locale.__createSettingsOrDefault(settings, {});
-
- var cleanSettings = {};
- if (settings.hasOwnProperty('skeleton')) {
- // Assign skeleton to cleanSettings and fix invalid currency pattern
- // if present - 'ooxo' becomes 'o'.
- cleanSettings['skeleton'] =
- settings['skeleton'].replace(/\u00a4+[^\u00a4]+\u00a4+/g, '\u00a4');
- } else if (settings.hasOwnProperty('pattern')) {
- cleanSettings['pattern'] = settings['pattern'];
- } else if (settings.hasOwnProperty('style')) {
- var style = settings['style'];
- if (!/^(decimal|currency|percent|scientific)$/.test(style)) {
- style = 'decimal';
- }
- cleanSettings['style'] = style;
- }
-
- // Default is to show decimal style.
- if (!cleanSettings.hasOwnProperty('skeleton') &&
- !cleanSettings.hasOwnProperty('pattern') &&
- !cleanSettings.hasOwnProperty('style')) {
- cleanSettings = {'style': 'decimal'};
- }
-
- // Add currency code if available and valid (3-letter ASCII code).
- if (settings.hasOwnProperty('currencyCode') &&
- /^[a-zA-Z]{3}$/.test(settings['currencyCode'])) {
- cleanSettings['currencyCode'] = settings['currencyCode'].toUpperCase();
- }
-
- locale = v8Locale.__createLocaleOrDefault(locale);
- // Pass in region ID for proper currency detection. Use ZZ if region is empty.
- var region = locale.options.regionID !== '' ? locale.options.regionID : 'ZZ';
- var formatter = NativeJSNumberFormat(
- locale.__icuLocaleID, 'und_' + region, cleanSettings);
-
- // ICU doesn't always uppercase the currency code.
- if (formatter.options.hasOwnProperty('currencyCode')) {
- formatter.options['currencyCode'] =
- formatter.options['currencyCode'].toUpperCase();
- }
-
- for (key in cleanSettings) {
- // Don't overwrite keys that are alredy in.
- if (formatter.options.hasOwnProperty(key)) continue;
-
- formatter.options[key] = cleanSettings[key];
- }
-
- /**
- * Clones existing number format with possible overrides for some
- * of the options.
- * @param {!Object} overrideSettings - overrides for current format settings.
- * @returns {Object} - new or cached NumberFormat object.
- * @public
- */
- formatter.derive = function(overrideSettings) {
- // To remove a setting user can specify undefined as its value. We'll remove
- // it from the map in that case.
- for (var prop in overrideSettings) {
- if (settings.hasOwnProperty(prop) && !overrideSettings[prop]) {
- delete settings[prop];
- }
- }
- return new v8Locale.__NumberFormat(
- locale, v8Locale.__createSettingsOrDefault(overrideSettings, settings));
- };
-
- return formatter;
-};
-
-/**
- * Creates new NumberFormat based on current locale.
- * @param {Object} - formatting flags. See constructor.
- * @returns {Object} - new or cached NumberFormat object.
- */
-v8Locale.prototype.createNumberFormat = function(settings) {
- return new v8Locale.__NumberFormat(this, settings);
-};
-
-/**
- * Merges user settings and defaults.
- * Settings that are not of object type are rejected.
- * Actual property values are not validated, but whitespace is trimmed if they
- * are strings.
- * @param {!Object} settings - user provided settings.
- * @param {!Object} defaults - default values for this type of settings.
- * @returns {Object} - valid settings object.
- * @private
- */
-v8Locale.__createSettingsOrDefault = function(settings, defaults) {
- if (!settings || typeof(settings) !== 'object' ) {
- return defaults;
- }
- for (var key in defaults) {
- if (!settings.hasOwnProperty(key)) {
- settings[key] = defaults[key];
- }
- }
- // Clean up settings.
- for (var key in settings) {
- // Trim whitespace.
- if (typeof(settings[key]) === "string") {
- settings[key] = settings[key].trim();
- }
- // Remove all properties that are set to undefined/null. This allows
- // derive method to remove a setting we don't need anymore.
- if (!settings[key]) {
- delete settings[key];
- }
- }
-
- return settings;
-};
-
-/**
- * If locale is valid (defined and of v8Locale type) we return it. If not
- * we create default locale and return it.
- * @param {!Object} locale - user provided locale.
- * @returns {Object} - v8Locale object.
- * @private
- */
-v8Locale.__createLocaleOrDefault = function(locale) {
- if (!locale || !(locale instanceof v8Locale)) {
- return new v8Locale();
- } else {
- return locale;
- }
-};
diff --git a/src/extensions/experimental/language-matcher.cc b/src/extensions/experimental/language-matcher.cc
deleted file mode 100644
index 127e571..0000000
--- a/src/extensions/experimental/language-matcher.cc
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// TODO(cira): Remove LanguageMatcher from v8 when ICU implements
-// language matching API.
-
-#include "src/extensions/experimental/language-matcher.h"
-
-#include <string.h>
-
-#include "src/extensions/experimental/i18n-utils.h"
-#include "unicode/datefmt.h" // For getAvailableLocales
-#include "unicode/locid.h"
-#include "unicode/uloc.h"
-
-namespace v8 {
-namespace internal {
-
-const unsigned int LanguageMatcher::kLanguageWeight = 75;
-const unsigned int LanguageMatcher::kScriptWeight = 20;
-const unsigned int LanguageMatcher::kRegionWeight = 5;
-const unsigned int LanguageMatcher::kThreshold = 50;
-const unsigned int LanguageMatcher::kPositionBonus = 1;
-const char* const LanguageMatcher::kDefaultLocale = "root";
-
-static const char* GetLanguageException(const char*);
-static bool BCP47ToICUFormat(const char*, char*);
-static int CompareLocaleSubtags(const char*, const char*);
-static bool BuildLocaleName(const char*, const char*, LocaleIDMatch*);
-
-LocaleIDMatch::LocaleIDMatch()
- : score(-1) {
- I18NUtils::StrNCopy(
- bcp47_id, ULOC_FULLNAME_CAPACITY, LanguageMatcher::kDefaultLocale);
-
- I18NUtils::StrNCopy(
- icu_id, ULOC_FULLNAME_CAPACITY, LanguageMatcher::kDefaultLocale);
-}
-
-LocaleIDMatch& LocaleIDMatch::operator=(const LocaleIDMatch& rhs) {
- I18NUtils::StrNCopy(this->bcp47_id, ULOC_FULLNAME_CAPACITY, rhs.bcp47_id);
- I18NUtils::StrNCopy(this->icu_id, ULOC_FULLNAME_CAPACITY, rhs.icu_id);
- this->score = rhs.score;
-
- return *this;
-}
-
-// static
-void LanguageMatcher::GetBestMatchForPriorityList(
- v8::Handle<v8::Array> locales, LocaleIDMatch* result) {
- v8::HandleScope handle_scope;
-
- unsigned int position_bonus = locales->Length() * kPositionBonus;
-
- int max_score = 0;
- LocaleIDMatch match;
- for (unsigned int i = 0; i < locales->Length(); ++i) {
- position_bonus -= kPositionBonus;
-
- v8::TryCatch try_catch;
- v8::Local<v8::Value> locale_id = locales->Get(v8::Integer::New(i));
-
- // Return default if exception is raised when reading parameter.
- if (try_catch.HasCaught()) break;
-
- // JavaScript arrays can be heterogenous so check each item
- // if it's a string.
- if (!locale_id->IsString()) continue;
-
- if (!CompareToSupportedLocaleIDList(locale_id->ToString(), &match)) {
- continue;
- }
-
- // Skip items under threshold.
- if (match.score < kThreshold) continue;
-
- match.score += position_bonus;
- if (match.score > max_score) {
- *result = match;
-
- max_score = match.score;
- }
- }
-}
-
-// static
-void LanguageMatcher::GetBestMatchForString(
- v8::Handle<v8::String> locale, LocaleIDMatch* result) {
- LocaleIDMatch match;
-
- if (CompareToSupportedLocaleIDList(locale, &match) &&
- match.score >= kThreshold) {
- *result = match;
- }
-}
-
-// static
-bool LanguageMatcher::CompareToSupportedLocaleIDList(
- v8::Handle<v8::String> locale_id, LocaleIDMatch* result) {
- static int32_t available_count = 0;
- // Depending on how ICU data is built, locales returned by
- // Locale::getAvailableLocale() are not guaranteed to support DateFormat,
- // Collation and other services. We can call getAvailableLocale() of all the
- // services we want to support and take the intersection of them all, but
- // using DateFormat::getAvailableLocales() should suffice.
- // TODO(cira): Maybe make this thread-safe?
- static const icu::Locale* available_locales =
- icu::DateFormat::getAvailableLocales(available_count);
-
- // Skip this locale_id if it's not in ASCII.
- static LocaleIDMatch default_match;
- v8::String::AsciiValue ascii_value(locale_id);
- if (*ascii_value == NULL) return false;
-
- char locale[ULOC_FULLNAME_CAPACITY];
- if (!BCP47ToICUFormat(*ascii_value, locale)) return false;
-
- icu::Locale input_locale(locale);
-
- // Position of the best match locale in list of available locales.
- int position = -1;
- const char* language = GetLanguageException(input_locale.getLanguage());
- const char* script = input_locale.getScript();
- const char* region = input_locale.getCountry();
- for (int32_t i = 0; i < available_count; ++i) {
- int current_score = 0;
- int sign =
- CompareLocaleSubtags(language, available_locales[i].getLanguage());
- current_score += sign * kLanguageWeight;
-
- sign = CompareLocaleSubtags(script, available_locales[i].getScript());
- current_score += sign * kScriptWeight;
-
- sign = CompareLocaleSubtags(region, available_locales[i].getCountry());
- current_score += sign * kRegionWeight;
-
- if (current_score >= kThreshold && current_score > result->score) {
- result->score = current_score;
- position = i;
- }
- }
-
- // Didn't find any good matches so use defaults.
- if (position == -1) return false;
-
- return BuildLocaleName(available_locales[position].getBaseName(),
- input_locale.getName(), result);
-}
-
-// For some unsupported language subtags it is better to fallback to related
-// language that is supported than to default.
-static const char* GetLanguageException(const char* language) {
- // Serbo-croatian to Serbian.
- if (!strcmp(language, "sh")) return "sr";
-
- // Norweigan to Norweiaan to Norwegian Bokmal.
- if (!strcmp(language, "no")) return "nb";
-
- // Moldavian to Romanian.
- if (!strcmp(language, "mo")) return "ro";
-
- // Tagalog to Filipino.
- if (!strcmp(language, "tl")) return "fil";
-
- return language;
-}
-
-// Converts user input from BCP47 locale id format to ICU compatible format.
-// Returns false if uloc_forLanguageTag call fails or if extension is too long.
-static bool BCP47ToICUFormat(const char* locale_id, char* result) {
- UErrorCode status = U_ZERO_ERROR;
- int32_t locale_size = 0;
-
- char locale[ULOC_FULLNAME_CAPACITY];
- I18NUtils::StrNCopy(locale, ULOC_FULLNAME_CAPACITY, locale_id);
-
- // uloc_forLanguageTag has a bug where long extension can crash the code.
- // We need to check if extension part of language id conforms to the length.
- // ICU bug: http://bugs.icu-project.org/trac/ticket/8519
- const char* extension = strstr(locale_id, "-u-");
- if (extension != NULL &&
- strlen(extension) > ULOC_KEYWORD_AND_VALUES_CAPACITY) {
- // Truncate to get non-crashing string, but still preserve base language.
- int base_length = strlen(locale_id) - strlen(extension);
- locale[base_length] = '\0';
- }
-
- uloc_forLanguageTag(locale, result, ULOC_FULLNAME_CAPACITY,
- &locale_size, &status);
- return !U_FAILURE(status);
-}
-
-// Compares locale id subtags.
-// Returns 1 for match or -1 for mismatch.
-static int CompareLocaleSubtags(const char* lsubtag, const char* rsubtag) {
- return strcmp(lsubtag, rsubtag) == 0 ? 1 : -1;
-}
-
-// Builds a BCP47 compliant locale id from base name of matched locale and
-// full user specified locale.
-// Returns false if uloc_toLanguageTag failed to convert locale id.
-// Example:
-// base_name of matched locale (ICU ID): de_DE
-// input_locale_name (ICU ID): de_AT@collation=phonebk
-// result (ICU ID): de_DE@collation=phonebk
-// result (BCP47 ID): de-DE-u-co-phonebk
-static bool BuildLocaleName(const char* base_name,
- const char* input_locale_name,
- LocaleIDMatch* result) {
- I18NUtils::StrNCopy(result->icu_id, ULOC_LANG_CAPACITY, base_name);
-
- // Get extensions (if any) from the original locale.
- const char* extension = strchr(input_locale_name, ULOC_KEYWORD_SEPARATOR);
- if (extension != NULL) {
- I18NUtils::StrNCopy(result->icu_id + strlen(base_name),
- ULOC_KEYWORD_AND_VALUES_CAPACITY, extension);
- } else {
- I18NUtils::StrNCopy(result->icu_id, ULOC_LANG_CAPACITY, base_name);
- }
-
- // Convert ICU locale name into BCP47 format.
- UErrorCode status = U_ZERO_ERROR;
- uloc_toLanguageTag(result->icu_id, result->bcp47_id,
- ULOC_FULLNAME_CAPACITY, false, &status);
- return !U_FAILURE(status);
-}
-
-} } // namespace v8::internal
diff --git a/src/extensions/experimental/language-matcher.h b/src/extensions/experimental/language-matcher.h
deleted file mode 100644
index dd29304..0000000
--- a/src/extensions/experimental/language-matcher.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_EXTENSIONS_EXPERIMENTAL_LANGUAGE_MATCHER_H_
-#define V8_EXTENSIONS_EXPERIMENTAL_LANGUAGE_MATCHER_H_
-
-#include "include/v8.h"
-
-#include "unicode/uloc.h"
-
-namespace v8 {
-namespace internal {
-
-struct LocaleIDMatch {
- LocaleIDMatch();
-
- LocaleIDMatch& operator=(const LocaleIDMatch& rhs);
-
- // Bcp47 locale id - "de-Latn-DE-u-co-phonebk".
- char bcp47_id[ULOC_FULLNAME_CAPACITY];
-
- // ICU locale id - "de_Latn_DE@collation=phonebk".
- char icu_id[ULOC_FULLNAME_CAPACITY];
-
- // Score for this locale.
- int score;
-};
-
-class LanguageMatcher {
- public:
- // Default locale.
- static const char* const kDefaultLocale;
-
- // Finds best supported locale for a given a list of locale identifiers.
- // It preserves the extension for the locale id.
- static void GetBestMatchForPriorityList(
- v8::Handle<v8::Array> locale_list, LocaleIDMatch* result);
-
- // Finds best supported locale for a single locale identifier.
- // It preserves the extension for the locale id.
- static void GetBestMatchForString(
- v8::Handle<v8::String> locale_id, LocaleIDMatch* result);
-
- private:
- // If langauge subtags match add this amount to the score.
- static const unsigned int kLanguageWeight;
-
- // If script subtags match add this amount to the score.
- static const unsigned int kScriptWeight;
-
- // If region subtags match add this amount to the score.
- static const unsigned int kRegionWeight;
-
- // LocaleID match score has to be over this number to accept the match.
- static const unsigned int kThreshold;
-
- // For breaking ties in priority queue.
- static const unsigned int kPositionBonus;
-
- LanguageMatcher();
-
- // Compares locale_id to the supported list of locales and returns best
- // match.
- // Returns false if it fails to convert locale id from ICU to BCP47 format.
- static bool CompareToSupportedLocaleIDList(v8::Handle<v8::String> locale_id,
- LocaleIDMatch* result);
-};
-
-} } // namespace v8::internal
-
-#endif // V8_EXTENSIONS_EXPERIMENTAL_LANGUAGE_MATCHER_H_
diff --git a/src/extensions/experimental/number-format.cc b/src/extensions/experimental/number-format.cc
deleted file mode 100644
index 2932c52..0000000
--- a/src/extensions/experimental/number-format.cc
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/extensions/experimental/number-format.h"
-
-#include <string.h>
-
-#include "src/extensions/experimental/i18n-utils.h"
-#include "unicode/dcfmtsym.h"
-#include "unicode/decimfmt.h"
-#include "unicode/locid.h"
-#include "unicode/numfmt.h"
-#include "unicode/uchar.h"
-#include "unicode/ucurr.h"
-#include "unicode/unum.h"
-#include "unicode/uversion.h"
-
-namespace v8 {
-namespace internal {
-
-const int NumberFormat::kCurrencyCodeLength = 4;
-
-v8::Persistent<v8::FunctionTemplate> NumberFormat::number_format_template_;
-
-static icu::DecimalFormat* CreateNumberFormat(v8::Handle<v8::String>,
- v8::Handle<v8::String>,
- v8::Handle<v8::Object>);
-static icu::DecimalFormat* CreateFormatterFromSkeleton(
- const icu::Locale&, const icu::UnicodeString&, UErrorCode*);
-static icu::DecimalFormatSymbols* GetFormatSymbols(const icu::Locale&);
-static bool GetCurrencyCode(const icu::Locale&,
- const char* const,
- v8::Handle<v8::Object>,
- UChar*);
-static v8::Handle<v8::Value> ThrowUnexpectedObjectError();
-
-icu::DecimalFormat* NumberFormat::UnpackNumberFormat(
- v8::Handle<v8::Object> obj) {
- if (number_format_template_->HasInstance(obj)) {
- return static_cast<icu::DecimalFormat*>(
- obj->GetPointerFromInternalField(0));
- }
-
- return NULL;
-}
-
-void NumberFormat::DeleteNumberFormat(v8::Persistent<v8::Value> object,
- void* param) {
- v8::Persistent<v8::Object> persistent_object =
- v8::Persistent<v8::Object>::Cast(object);
-
- // First delete the hidden C++ object.
- // Unpacking should never return NULL here. That would only happen if
- // this method is used as the weak callback for persistent handles not
- // pointing to a number formatter.
- delete UnpackNumberFormat(persistent_object);
-
- // Then dispose of the persistent handle to JS object.
- persistent_object.Dispose();
-}
-
-v8::Handle<v8::Value> NumberFormat::Format(const v8::Arguments& args) {
- v8::HandleScope handle_scope;
-
- if (args.Length() != 1 || !args[0]->IsNumber()) {
- // Just return NaN on invalid input.
- return v8::String::New("NaN");
- }
-
- icu::DecimalFormat* number_format = UnpackNumberFormat(args.Holder());
- if (!number_format) {
- return ThrowUnexpectedObjectError();
- }
-
- // ICU will handle actual NaN value properly and return NaN string.
- icu::UnicodeString result;
- number_format->format(args[0]->NumberValue(), result);
-
- return v8::String::New(
- reinterpret_cast<const uint16_t*>(result.getBuffer()), result.length());
-}
-
-v8::Handle<v8::Value> NumberFormat::JSNumberFormat(const v8::Arguments& args) {
- v8::HandleScope handle_scope;
-
- // Expect locale id, region id and settings.
- if (args.Length() != 3 ||
- !args[0]->IsString() || !args[1]->IsString() || !args[2]->IsObject()) {
- return v8::ThrowException(v8::Exception::SyntaxError(
- v8::String::New("Locale, region and number settings are required.")));
- }
-
- icu::DecimalFormat* number_format = CreateNumberFormat(
- args[0]->ToString(), args[1]->ToString(), args[2]->ToObject());
-
- if (number_format_template_.IsEmpty()) {
- v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New());
-
- raw_template->SetClassName(v8::String::New("v8Locale.NumberFormat"));
-
- // Define internal field count on instance template.
- v8::Local<v8::ObjectTemplate> object_template =
- raw_template->InstanceTemplate();
-
- // Set aside internal field for icu number formatter.
- object_template->SetInternalFieldCount(1);
-
- // Define all of the prototype methods on prototype template.
- v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate();
- proto->Set(v8::String::New("format"),
- v8::FunctionTemplate::New(Format));
-
- number_format_template_ =
- v8::Persistent<v8::FunctionTemplate>::New(raw_template);
- }
-
- // Create an empty object wrapper.
- v8::Local<v8::Object> local_object =
- number_format_template_->GetFunction()->NewInstance();
- v8::Persistent<v8::Object> wrapper =
- v8::Persistent<v8::Object>::New(local_object);
-
- // Set number formatter as internal field of the resulting JS object.
- wrapper->SetPointerInInternalField(0, number_format);
-
- // Create options key.
- v8::Local<v8::Object> options = v8::Object::New();
-
- // Show what ICU decided to use for easier problem tracking.
- // Keep it as v8 specific extension.
- icu::UnicodeString pattern;
- number_format->toPattern(pattern);
- options->Set(v8::String::New("v8ResolvedPattern"),
- v8::String::New(reinterpret_cast<const uint16_t*>(
- pattern.getBuffer()), pattern.length()));
-
- // Set resolved currency code in options.currency if not empty.
- icu::UnicodeString currency(number_format->getCurrency());
- if (!currency.isEmpty()) {
- options->Set(v8::String::New("currencyCode"),
- v8::String::New(reinterpret_cast<const uint16_t*>(
- currency.getBuffer()), currency.length()));
- }
-
- wrapper->Set(v8::String::New("options"), options);
-
- // Make object handle weak so we can delete iterator once GC kicks in.
- wrapper.MakeWeak(NULL, DeleteNumberFormat);
-
- return wrapper;
-}
-
-// Returns DecimalFormat.
-static icu::DecimalFormat* CreateNumberFormat(v8::Handle<v8::String> locale,
- v8::Handle<v8::String> region,
- v8::Handle<v8::Object> settings) {
- v8::HandleScope handle_scope;
-
- v8::String::AsciiValue ascii_locale(locale);
- icu::Locale icu_locale(*ascii_locale);
-
- // Make formatter from skeleton.
- icu::DecimalFormat* number_format = NULL;
- UErrorCode status = U_ZERO_ERROR;
- icu::UnicodeString setting;
-
- if (I18NUtils::ExtractStringSetting(settings, "skeleton", &setting)) {
- // TODO(cira): Use ICU skeleton once
- // http://bugs.icu-project.org/trac/ticket/8610 is resolved.
- number_format = CreateFormatterFromSkeleton(icu_locale, setting, &status);
- } else if (I18NUtils::ExtractStringSetting(settings, "pattern", &setting)) {
- number_format =
- new icu::DecimalFormat(setting, GetFormatSymbols(icu_locale), status);
- } else if (I18NUtils::ExtractStringSetting(settings, "style", &setting)) {
- if (setting == UNICODE_STRING_SIMPLE("currency")) {
- number_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createCurrencyInstance(icu_locale, status));
- } else if (setting == UNICODE_STRING_SIMPLE("percent")) {
- number_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createPercentInstance(icu_locale, status));
- } else if (setting == UNICODE_STRING_SIMPLE("scientific")) {
- number_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createScientificInstance(icu_locale, status));
- } else {
- // Make it decimal in any other case.
- number_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createInstance(icu_locale, status));
- }
- }
-
- if (U_FAILURE(status)) {
- delete number_format;
- status = U_ZERO_ERROR;
- number_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createInstance(icu_locale, status));
- }
-
- // Attach appropriate currency code to the formatter.
- // It affects currency formatters only.
- // Region is full language identifier in form 'und_' + region id.
- v8::String::AsciiValue ascii_region(region);
-
- UChar currency_code[NumberFormat::kCurrencyCodeLength];
- if (GetCurrencyCode(icu_locale, *ascii_region, settings, currency_code)) {
- number_format->setCurrency(currency_code, status);
- }
-
- return number_format;
-}
-
-// Generates ICU number format pattern from given skeleton.
-// TODO(cira): Remove once ICU includes equivalent method
-// (see http://bugs.icu-project.org/trac/ticket/8610).
-static icu::DecimalFormat* CreateFormatterFromSkeleton(
- const icu::Locale& icu_locale,
- const icu::UnicodeString& skeleton,
- UErrorCode* status) {
- icu::DecimalFormat skeleton_format(
- skeleton, GetFormatSymbols(icu_locale), *status);
-
- // Find out if skeleton contains currency or percent symbol and create
- // proper instance to tweak.
- icu::DecimalFormat* base_format = NULL;
-
- // UChar representation of U+00A4 currency symbol.
- const UChar currency_symbol = 0xA4u;
-
- int32_t index = skeleton.indexOf(currency_symbol);
- if (index != -1) {
- // Find how many U+00A4 are there. There is at least one.
- // Case of non-consecutive U+00A4 is taken care of in i18n.js.
- int32_t end_index = skeleton.lastIndexOf(currency_symbol, index);
-
-#if (U_ICU_VERSION_MAJOR_NUM == 4) && (U_ICU_VERSION_MINOR_NUM <= 6)
- icu::NumberFormat::EStyles style;
- switch (end_index - index) {
- case 0:
- style = icu::NumberFormat::kCurrencyStyle;
- break;
- case 1:
- style = icu::NumberFormat::kIsoCurrencyStyle;
- break;
- default:
- style = icu::NumberFormat::kPluralCurrencyStyle;
- }
-#else // ICU version is 4.8 or above (we ignore versions below 4.0).
- UNumberFormatStyle style;
- switch (end_index - index) {
- case 0:
- style = UNUM_CURRENCY;
- break;
- case 1:
- style = UNUM_CURRENCY_ISO;
- break;
- default:
- style = UNUM_CURRENCY_PLURAL;
- }
-#endif
-
- base_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createInstance(icu_locale, style, *status));
- } else if (skeleton.indexOf('%') != -1) {
- base_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createPercentInstance(icu_locale, *status));
- } else {
- // TODO(cira): Handle scientific skeleton.
- base_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createInstance(icu_locale, *status));
- }
-
- if (U_FAILURE(*status)) {
- delete base_format;
- return NULL;
- }
-
- // Copy important information from skeleton to the new formatter.
- // TODO(cira): copy rounding information from skeleton?
- base_format->setGroupingUsed(skeleton_format.isGroupingUsed());
-
- base_format->setMinimumIntegerDigits(
- skeleton_format.getMinimumIntegerDigits());
-
- base_format->setMinimumFractionDigits(
- skeleton_format.getMinimumFractionDigits());
-
- base_format->setMaximumFractionDigits(
- skeleton_format.getMaximumFractionDigits());
-
- return base_format;
-}
-
-// Gets decimal symbols for a locale.
-static icu::DecimalFormatSymbols* GetFormatSymbols(
- const icu::Locale& icu_locale) {
- UErrorCode status = U_ZERO_ERROR;
- icu::DecimalFormatSymbols* symbols =
- new icu::DecimalFormatSymbols(icu_locale, status);
-
- if (U_FAILURE(status)) {
- delete symbols;
- // Use symbols from default locale.
- symbols = new icu::DecimalFormatSymbols(status);
- }
-
- return symbols;
-}
-
-// Gets currency ISO 4217 3-letter code.
-// Check currencyCode setting first, then @currency=code and in the end
-// try to infer currency code from locale in the form 'und_' + region id.
-// Returns false in case of error.
-static bool GetCurrencyCode(const icu::Locale& icu_locale,
- const char* const und_region_locale,
- v8::Handle<v8::Object> settings,
- UChar* code) {
- UErrorCode status = U_ZERO_ERROR;
-
- // If there is user specified currency code, use it.
- icu::UnicodeString currency;
- if (I18NUtils::ExtractStringSetting(settings, "currencyCode", ¤cy)) {
- currency.extract(code, NumberFormat::kCurrencyCodeLength, status);
- return true;
- }
-
- // If ICU locale has -cu- currency code use it.
- char currency_code[NumberFormat::kCurrencyCodeLength];
- int32_t length = icu_locale.getKeywordValue(
- "currency", currency_code, NumberFormat::kCurrencyCodeLength, status);
- if (length != 0) {
- I18NUtils::AsciiToUChar(currency_code, length + 1,
- code, NumberFormat::kCurrencyCodeLength);
- return true;
- }
-
- // Otherwise infer currency code from the region id.
- ucurr_forLocale(
- und_region_locale, code, NumberFormat::kCurrencyCodeLength, &status);
-
- return !!U_SUCCESS(status);
-}
-
-// Throws a JavaScript exception.
-static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
- // Returns undefined, and schedules an exception to be thrown.
- return v8::ThrowException(v8::Exception::Error(
- v8::String::New("NumberFormat method called on an object "
- "that is not a NumberFormat.")));
-}
-
-} } // namespace v8::internal
diff --git a/src/extensions/experimental/number-format.h b/src/extensions/experimental/number-format.h
deleted file mode 100644
index bcfaed6..0000000
--- a/src/extensions/experimental/number-format.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2011 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_EXTENSIONS_EXPERIMENTAL_NUMBER_FORMAT_H_
-#define V8_EXTENSIONS_EXPERIMENTAL_NUMBER_FORMAT_H_
-
-#include "include/v8.h"
-
-#include "unicode/uversion.h"
-
-namespace U_ICU_NAMESPACE {
-class DecimalFormat;
-}
-
-namespace v8 {
-namespace internal {
-
-class NumberFormat {
- public:
- // 3-letter ISO 4217 currency code plus \0.
- static const int kCurrencyCodeLength;
-
- static v8::Handle<v8::Value> JSNumberFormat(const v8::Arguments& args);
-
- // Helper methods for various bindings.
-
- // Unpacks date format object from corresponding JavaScript object.
- static icu::DecimalFormat* UnpackNumberFormat(
- v8::Handle<v8::Object> obj);
-
- // Release memory we allocated for the NumberFormat once the JS object that
- // holds the pointer gets garbage collected.
- static void DeleteNumberFormat(v8::Persistent<v8::Value> object,
- void* param);
-
- // Formats number and returns corresponding string.
- static v8::Handle<v8::Value> Format(const v8::Arguments& args);
-
- private:
- NumberFormat();
-
- static v8::Persistent<v8::FunctionTemplate> number_format_template_;
-};
-
-} } // namespace v8::internal
-
-#endif // V8_EXTENSIONS_EXPERIMENTAL_NUMBER_FORMAT_H_
diff --git a/src/full-codegen.h b/src/full-codegen.h
index a1368c2..0270e13 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -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:
@@ -142,11 +142,13 @@
return previous_;
}
- protected:
+ protected:
MacroAssembler* masm() { return codegen_->masm(); }
FullCodeGenerator* codegen_;
NestedStatement* previous_;
+
+ private:
DISALLOW_COPY_AND_ASSIGN(NestedStatement);
};
diff --git a/src/heap.cc b/src/heap.cc
index fff1319..d97f337 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -583,7 +583,9 @@
PagedSpace* cell_space = Heap::cell_space();
LargeObjectSpace* lo_space = Heap::lo_space();
bool gc_performed = true;
- while (gc_performed) {
+ int counter = 0;
+ static const int kThreshold = 20;
+ while (gc_performed && counter++ < kThreshold) {
gc_performed = false;
if (!new_space->ReserveSpace(new_space_size)) {
Heap::CollectGarbage(NEW_SPACE);
@@ -622,6 +624,11 @@
gc_performed = true;
}
}
+
+ if (gc_performed) {
+ // Failed to reserve the space after several attempts.
+ V8::FatalProcessOutOfMemory("Heap::ReserveSpace");
+ }
}
@@ -6515,11 +6522,17 @@
int KeyedLookupCache::Lookup(Map* map, String* name) {
- int index = Hash(map, name);
+ int index = (Hash(map, name) & kHashMask);
Key& key = keys_[index];
if ((key.map == map) && key.name->Equals(name)) {
return field_offsets_[index];
}
+ ASSERT(kEntriesPerBucket == 2); // There are two entries to check.
+ // First entry in the bucket missed, check the second.
+ Key& key2 = keys_[index + 1];
+ if ((key2.map == map) && key2.name->Equals(name)) {
+ return field_offsets_[index + 1];
+ }
return kNotFound;
}
@@ -6527,8 +6540,14 @@
void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
String* symbol;
if (HEAP->LookupSymbolIfExists(name, &symbol)) {
- int index = Hash(map, symbol);
+ int index = (Hash(map, symbol) & kHashMask);
Key& key = keys_[index];
+ Key& key2 = keys_[index + 1]; // Second entry in the bucket.
+ // Demote the first entry to the second in the bucket.
+ key2.map = key.map;
+ key2.name = key.name;
+ field_offsets_[index + 1] = field_offsets_[index];
+ // Write the new first entry.
key.map = map;
key.name = symbol;
field_offsets_[index] = field_offset;
diff --git a/src/heap.h b/src/heap.h
index 937b034..85df55e 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -2135,9 +2135,11 @@
// Clear the cache.
void Clear();
- static const int kLength = 64;
+ static const int kLength = 128;
static const int kCapacityMask = kLength - 1;
- static const int kMapHashShift = 2;
+ static const int kMapHashShift = 5;
+ static const int kHashMask = -2; // Zero the last bit.
+ static const int kEntriesPerBucket = 2;
static const int kNotFound = -1;
private:
@@ -2613,6 +2615,7 @@
AssertNoAllocation no_alloc; // i.e. no gc allowed.
+ private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PathTracer);
};
#endif // DEBUG || LIVE_OBJECT_LIST
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 887e80a..2d32ad1 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -416,18 +416,18 @@
void HValue::PrintChangesTo(StringStream* stream) {
- int changes_flags = ChangesFlags();
- if (changes_flags == 0) return;
+ GVNFlagSet changes_flags = ChangesFlags();
+ if (changes_flags.IsEmpty()) return;
stream->Add(" changes[");
- if (changes_flags == AllSideEffects()) {
+ if (changes_flags == AllSideEffectsFlagSet()) {
stream->Add("*");
} else {
bool add_comma = false;
-#define PRINT_DO(type) \
- if (changes_flags & (1 << kChanges##type)) { \
- if (add_comma) stream->Add(","); \
- add_comma = true; \
- stream->Add(#type); \
+#define PRINT_DO(type) \
+ if (changes_flags.Contains(kChanges##type)) { \
+ if (add_comma) stream->Add(","); \
+ add_comma = true; \
+ stream->Add(#type); \
}
GVN_FLAG_LIST(PRINT_DO);
#undef PRINT_DO
@@ -1408,21 +1408,21 @@
SetOperandAt(0, context);
SetOperandAt(1, object);
set_representation(Representation::Tagged());
- SetFlag(kDependsOnMaps);
+ SetGVNFlag(kDependsOnMaps);
for (int i = 0;
i < types->length() && types_.length() < kMaxLoadPolymorphism;
++i) {
Handle<Map> map = types->at(i);
LookupResult lookup(map->GetIsolate());
map->LookupInDescriptors(NULL, *name, &lookup);
- if (lookup.IsProperty()) {
+ if (lookup.IsFound()) {
switch (lookup.type()) {
case FIELD: {
int index = lookup.GetLocalFieldIndexFromMap(*map);
if (index < 0) {
- SetFlag(kDependsOnInobjectFields);
+ SetGVNFlag(kDependsOnInobjectFields);
} else {
- SetFlag(kDependsOnBackingStoreFields);
+ SetGVNFlag(kDependsOnBackingStoreFields);
}
types_.Add(types->at(i));
break;
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 5082e4d..9f661d6 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -492,18 +492,26 @@
};
+// There must be one corresponding kDepends flag for every kChanges flag and
+// the order of the kChanges flags must be exactly the same as of the kDepends
+// flags.
+enum GVNFlag {
+ // Declare global value numbering flags.
+#define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
+ GVN_FLAG_LIST(DECLARE_FLAG)
+#undef DECLARE_FLAG
+ kAfterLastFlag,
+ kLastFlag = kAfterLastFlag - 1
+};
+
+typedef EnumSet<GVNFlag> GVNFlagSet;
+
+
class HValue: public ZoneObject {
public:
static const int kNoNumber = -1;
- // There must be one corresponding kDepends flag for every kChanges flag and
- // the order of the kChanges flags must be exactly the same as of the kDepends
- // flags.
enum Flag {
- // Declare global value numbering flags.
- #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
- GVN_FLAG_LIST(DECLARE_DO)
- #undef DECLARE_DO
kFlexibleRepresentation,
// Participate in Global Value Numbering, i.e. elimination of
// unnecessary recomputations. If an instruction sets this flag, it must
@@ -523,8 +531,8 @@
static const int kChangesToDependsFlagsLeftShift = 1;
- static int ConvertChangesToDependsFlags(int flags) {
- return flags << kChangesToDependsFlagsLeftShift;
+ static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
+ return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
}
static HValue* cast(HValue* value) { return value; }
@@ -622,16 +630,32 @@
void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
- void SetAllSideEffects() { flags_ |= AllSideEffects(); }
- void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
- bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
+ GVNFlagSet gvn_flags() const { return gvn_flags_; }
+ void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
+ void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
+ bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
+ void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
+ void ClearAllSideEffects() {
+ gvn_flags_.Remove(AllSideEffectsFlagSet());
+ }
+ bool HasSideEffects() const {
+ return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
+ }
bool HasObservableSideEffects() const {
- return (flags_ & ObservableSideEffects()) != 0;
+ return gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
}
- int ChangesFlags() const { return flags_ & ChangesFlagsMask(); }
- int ObservableChangesFlags() const {
- return flags_ & ChangesFlagsMask() & ObservableSideEffects();
+ GVNFlagSet ChangesFlags() const {
+ GVNFlagSet result = gvn_flags_;
+ result.Intersect(AllChangesFlagSet());
+ return result;
+ }
+
+ GVNFlagSet ObservableChangesFlags() const {
+ GVNFlagSet result = gvn_flags_;
+ result.Intersect(AllChangesFlagSet());
+ result.Intersect(AllObservableSideEffectsFlagSet());
+ return result;
}
Range* range() const { return range_; }
@@ -697,25 +721,28 @@
representation_ = r;
}
- private:
- static int ChangesFlagsMask() {
- int result = 0;
+ static GVNFlagSet AllChangesFlagSet() {
+ GVNFlagSet result;
// Create changes mask.
-#define ADD_FLAG(type) result |= (1 << kChanges##type);
+#define ADD_FLAG(type) result.Add(kChanges##type);
GVN_FLAG_LIST(ADD_FLAG)
#undef ADD_FLAG
return result;
}
// A flag mask to mark an instruction as having arbitrary side effects.
- static int AllSideEffects() {
- return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
+ static GVNFlagSet AllSideEffectsFlagSet() {
+ GVNFlagSet result = AllChangesFlagSet();
+ result.Remove(kChangesOsrEntries);
+ return result;
}
// A flag mask of all side effects that can make observable changes in
// an executing program (i.e. are not safe to repeat, move or remove);
- static int ObservableSideEffects() {
- return ChangesFlagsMask() & ~(1 << kChangesElementsKind);
+ static GVNFlagSet AllObservableSideEffectsFlagSet() {
+ GVNFlagSet result = AllChangesFlagSet();
+ result.Remove(kChangesElementsKind);
+ return result;
}
// Remove the matching use from the use list if present. Returns the
@@ -735,6 +762,7 @@
HUseListNode* use_list_;
Range* range_;
int flags_;
+ GVNFlagSet gvn_flags_;
DISALLOW_COPY_AND_ASSIGN(HValue);
};
@@ -772,7 +800,7 @@
: next_(NULL),
previous_(NULL),
position_(RelocInfo::kNoPosition) {
- SetFlag(kDependsOnOsrEntries);
+ SetGVNFlag(kDependsOnOsrEntries);
}
virtual void DeleteFromGraph() { Unlink(); }
@@ -1716,8 +1744,8 @@
SetOperandAt(1, typecheck);
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnArrayLengths);
- SetFlag(kDependsOnMaps);
+ SetGVNFlag(kDependsOnArrayLengths);
+ SetGVNFlag(kDependsOnMaps);
}
virtual Representation RequiredInputRepresentation(int index) {
@@ -1741,7 +1769,7 @@
explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnArrayLengths);
+ SetGVNFlag(kDependsOnArrayLengths);
}
virtual Representation RequiredInputRepresentation(int index) {
@@ -1760,7 +1788,7 @@
explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
set_representation(Representation::Integer32());
SetFlag(kUseGVN);
- SetFlag(kDependsOnElementsKind);
+ SetGVNFlag(kDependsOnElementsKind);
}
virtual Representation RequiredInputRepresentation(int index) {
@@ -1886,8 +1914,8 @@
explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnMaps);
- SetFlag(kDependsOnElementsKind);
+ SetGVNFlag(kDependsOnMaps);
+ SetGVNFlag(kDependsOnElementsKind);
}
virtual Representation RequiredInputRepresentation(int index) {
@@ -1937,7 +1965,7 @@
SetOperandAt(1, typecheck != NULL ? typecheck : value);
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnMaps);
+ SetGVNFlag(kDependsOnMaps);
has_element_transitions_ =
map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL) != NULL ||
map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL) != NULL;
@@ -2105,7 +2133,7 @@
HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
: prototype_(prototype), holder_(holder) {
SetFlag(kUseGVN);
- SetFlag(kDependsOnMaps);
+ SetGVNFlag(kDependsOnMaps);
}
#ifdef DEBUG
@@ -3255,7 +3283,7 @@
class HOsrEntry: public HTemplateInstruction<0> {
public:
explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
- SetFlag(kChangesOsrEntries);
+ SetGVNFlag(kChangesOsrEntries);
}
int ast_id() const { return ast_id_; }
@@ -3343,7 +3371,7 @@
: cell_(cell), details_(details) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnGlobalVars);
+ SetGVNFlag(kDependsOnGlobalVars);
}
Handle<JSGlobalPropertyCell> cell() const { return cell_; }
@@ -3422,7 +3450,7 @@
: HUnaryOperation(value),
cell_(cell),
details_(details) {
- SetFlag(kChangesGlobalVars);
+ SetGVNFlag(kChangesGlobalVars);
}
Handle<JSGlobalPropertyCell> cell() const { return cell_; }
@@ -3513,7 +3541,7 @@
}
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnContextSlots);
+ SetGVNFlag(kDependsOnContextSlots);
}
int slot_index() const { return slot_index_; }
@@ -3566,7 +3594,7 @@
: slot_index_(slot_index), mode_(mode) {
SetOperandAt(0, context);
SetOperandAt(1, value);
- SetFlag(kChangesContextSlots);
+ SetGVNFlag(kChangesContextSlots);
}
HValue* context() { return OperandAt(0); }
@@ -3608,11 +3636,11 @@
offset_(offset) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnMaps);
+ SetGVNFlag(kDependsOnMaps);
if (is_in_object) {
- SetFlag(kDependsOnInobjectFields);
+ SetGVNFlag(kDependsOnInobjectFields);
} else {
- SetFlag(kDependsOnBackingStoreFields);
+ SetGVNFlag(kDependsOnBackingStoreFields);
}
}
@@ -3706,7 +3734,7 @@
: HUnaryOperation(function) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnCalls);
+ SetGVNFlag(kDependsOnCalls);
}
HValue* function() { return OperandAt(0); }
@@ -3728,7 +3756,7 @@
SetOperandAt(0, obj);
SetOperandAt(1, key);
set_representation(Representation::Tagged());
- SetFlag(kDependsOnArrayElements);
+ SetGVNFlag(kDependsOnArrayElements);
SetFlag(kUseGVN);
}
@@ -3759,7 +3787,7 @@
SetOperandAt(0, elements);
SetOperandAt(1, key);
set_representation(Representation::Double());
- SetFlag(kDependsOnDoubleArrayElements);
+ SetGVNFlag(kDependsOnDoubleArrayElements);
SetFlag(kUseGVN);
}
@@ -3796,9 +3824,9 @@
} else {
set_representation(Representation::Integer32());
}
- SetFlag(kDependsOnSpecializedArrayElements);
+ SetGVNFlag(kDependsOnSpecializedArrayElements);
// Native code could change the specialized array.
- SetFlag(kDependsOnCalls);
+ SetGVNFlag(kDependsOnCalls);
SetFlag(kUseGVN);
}
@@ -3868,9 +3896,9 @@
SetOperandAt(0, obj);
SetOperandAt(1, val);
if (is_in_object_) {
- SetFlag(kChangesInobjectFields);
+ SetGVNFlag(kChangesInobjectFields);
} else {
- SetFlag(kChangesBackingStoreFields);
+ SetGVNFlag(kChangesBackingStoreFields);
}
}
@@ -3945,7 +3973,7 @@
SetOperandAt(0, obj);
SetOperandAt(1, key);
SetOperandAt(2, val);
- SetFlag(kChangesArrayElements);
+ SetGVNFlag(kChangesArrayElements);
}
virtual Representation RequiredInputRepresentation(int index) {
@@ -3987,7 +4015,7 @@
SetOperandAt(0, elements);
SetOperandAt(1, key);
SetOperandAt(2, val);
- SetFlag(kChangesDoubleArrayElements);
+ SetGVNFlag(kChangesDoubleArrayElements);
}
virtual Representation RequiredInputRepresentation(int index) {
@@ -4021,7 +4049,7 @@
HValue* val,
ElementsKind elements_kind)
: elements_kind_(elements_kind) {
- SetFlag(kChangesSpecializedArrayElements);
+ SetGVNFlag(kChangesSpecializedArrayElements);
SetOperandAt(0, external_elements);
SetOperandAt(1, key);
SetOperandAt(2, val);
@@ -4099,7 +4127,7 @@
transitioned_map_(transitioned_map) {
SetOperandAt(0, object);
SetFlag(kUseGVN);
- SetFlag(kChangesElementsKind);
+ SetGVNFlag(kChangesElementsKind);
set_representation(Representation::Tagged());
}
@@ -4134,7 +4162,7 @@
: HBinaryOperation(context, left, right) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnMaps);
+ SetGVNFlag(kDependsOnMaps);
}
virtual Representation RequiredInputRepresentation(int index) {
@@ -4160,7 +4188,7 @@
SetOperandAt(2, index);
set_representation(Representation::Integer32());
SetFlag(kUseGVN);
- SetFlag(kDependsOnMaps);
+ SetGVNFlag(kDependsOnMaps);
}
virtual Representation RequiredInputRepresentation(int index) {
@@ -4215,7 +4243,7 @@
explicit HStringLength(HValue* string) : HUnaryOperation(string) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnMaps);
+ SetGVNFlag(kDependsOnMaps);
}
virtual Representation RequiredInputRepresentation(int index) {
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 56da2dc..1a63f1e 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1110,10 +1110,10 @@
}
-void HValueMap::Kill(int flags) {
- int depends_flags = HValue::ConvertChangesToDependsFlags(flags);
- if ((present_flags_ & depends_flags) == 0) return;
- present_flags_ = 0;
+void HValueMap::Kill(GVNFlagSet flags) {
+ GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(flags);
+ if (!present_flags_.ContainsAnyOf(depends_flags)) return;
+ present_flags_.RemoveAll();
for (int i = 0; i < array_size_; ++i) {
HValue* value = array_[i].value;
if (value != NULL) {
@@ -1122,7 +1122,8 @@
int next;
for (int current = array_[i].next; current != kNil; current = next) {
next = lists_[current].next;
- if ((lists_[current].value->flags() & depends_flags) != 0) {
+ HValue* value = lists_[current].value;
+ if (value->gvn_flags().ContainsAnyOf(depends_flags)) {
// Drop it.
count_--;
lists_[current].next = free_list_head_;
@@ -1131,13 +1132,14 @@
// Keep it.
lists_[current].next = kept;
kept = current;
- present_flags_ |= lists_[current].value->flags();
+ present_flags_.Add(value->gvn_flags());
}
}
array_[i].next = kept;
// Now possibly drop directly indexed element.
- if ((array_[i].value->flags() & depends_flags) != 0) { // Drop it.
+ value = array_[i].value;
+ if (value->gvn_flags().ContainsAnyOf(depends_flags)) { // Drop it.
count_--;
int head = array_[i].next;
if (head == kNil) {
@@ -1149,7 +1151,7 @@
free_list_head_ = head;
}
} else {
- present_flags_ |= array_[i].value->flags(); // Keep it.
+ present_flags_.Add(value->gvn_flags()); // Keep it.
}
}
}
@@ -1356,8 +1358,8 @@
loop_side_effects_(graph->blocks()->length()),
visited_on_paths_(graph->zone(), graph->blocks()->length()) {
ASSERT(info->isolate()->heap()->allow_allocation(false));
- block_side_effects_.AddBlock(0, graph_->blocks()->length());
- loop_side_effects_.AddBlock(0, graph_->blocks()->length());
+ block_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
+ loop_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
}
~HGlobalValueNumberer() {
ASSERT(!info_->isolate()->heap()->allow_allocation(true));
@@ -1367,14 +1369,15 @@
bool Analyze();
private:
- int CollectSideEffectsOnPathsToDominatedBlock(HBasicBlock* dominator,
- HBasicBlock* dominated);
+ GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
+ HBasicBlock* dominator,
+ HBasicBlock* dominated);
void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
void ComputeBlockSideEffects();
void LoopInvariantCodeMotion();
void ProcessLoopBlock(HBasicBlock* block,
HBasicBlock* before_loop,
- int loop_kills);
+ GVNFlagSet loop_kills);
bool AllowCodeMotion();
bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
@@ -1387,10 +1390,10 @@
bool removed_side_effects_;
// A map of block IDs to their side effects.
- ZoneList<int> block_side_effects_;
+ ZoneList<GVNFlagSet> block_side_effects_;
// A map of loop header block IDs to their loop's side effects.
- ZoneList<int> loop_side_effects_;
+ ZoneList<GVNFlagSet> loop_side_effects_;
// Used when collecting side effects on paths from dominator to
// dominated.
@@ -1415,23 +1418,24 @@
HBasicBlock* block = graph_->blocks()->at(i);
HInstruction* instr = block->first();
int id = block->block_id();
- int side_effects = 0;
+ GVNFlagSet side_effects;
while (instr != NULL) {
- side_effects |= instr->ChangesFlags();
+ side_effects.Add(instr->ChangesFlags());
instr = instr->next();
}
- block_side_effects_[id] |= side_effects;
+ block_side_effects_[id].Add(side_effects);
// Loop headers are part of their loop.
if (block->IsLoopHeader()) {
- loop_side_effects_[id] |= side_effects;
+ loop_side_effects_[id].Add(side_effects);
}
// Propagate loop side effects upwards.
if (block->HasParentLoopHeader()) {
int header_id = block->parent_loop_header()->block_id();
- loop_side_effects_[header_id] |=
- block->IsLoopHeader() ? loop_side_effects_[id] : side_effects;
+ loop_side_effects_[header_id].Add(block->IsLoopHeader()
+ ? loop_side_effects_[id]
+ : side_effects);
}
}
}
@@ -1441,10 +1445,10 @@
for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
HBasicBlock* block = graph_->blocks()->at(i);
if (block->IsLoopHeader()) {
- int side_effects = loop_side_effects_[block->block_id()];
+ GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n",
block->block_id(),
- side_effects);
+ side_effects.ToIntegral());
HBasicBlock* last = block->loop_information()->GetLastBackEdge();
for (int j = block->block_id(); j <= last->block_id(); ++j) {
@@ -1457,17 +1461,17 @@
void HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block,
HBasicBlock* loop_header,
- int loop_kills) {
+ GVNFlagSet loop_kills) {
HBasicBlock* pre_header = loop_header->predecessors()->at(0);
- int depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
+ GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n",
block->block_id(),
- depends_flags);
+ depends_flags.ToIntegral());
HInstruction* instr = block->first();
while (instr != NULL) {
HInstruction* next = instr->next();
if (instr->CheckFlag(HValue::kUseGVN) &&
- (instr->flags() & depends_flags) == 0) {
+ !instr->gvn_flags().ContainsAnyOf(depends_flags)) {
TraceGVN("Checking instruction %d (%s)\n",
instr->id(),
instr->Mnemonic());
@@ -1503,20 +1507,20 @@
}
-int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
+GVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
HBasicBlock* dominator, HBasicBlock* dominated) {
- int side_effects = 0;
+ GVNFlagSet side_effects;
for (int i = 0; i < dominated->predecessors()->length(); ++i) {
HBasicBlock* block = dominated->predecessors()->at(i);
if (dominator->block_id() < block->block_id() &&
block->block_id() < dominated->block_id() &&
visited_on_paths_.Add(block->block_id())) {
- side_effects |= block_side_effects_[block->block_id()];
+ side_effects.Add(block_side_effects_[block->block_id()]);
if (block->IsLoopHeader()) {
- side_effects |= loop_side_effects_[block->block_id()];
+ side_effects.Add(loop_side_effects_[block->block_id()]);
}
- side_effects |= CollectSideEffectsOnPathsToDominatedBlock(
- dominator, block);
+ side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock(
+ dominator, block));
}
}
return side_effects;
@@ -1537,8 +1541,8 @@
HInstruction* instr = block->first();
while (instr != NULL) {
HInstruction* next = instr->next();
- int flags = instr->ChangesFlags();
- if (flags != 0) {
+ GVNFlagSet flags = instr->ChangesFlags();
+ if (!flags.IsEmpty()) {
// Clear all instructions in the map that are affected by side effects.
map->Kill(flags);
TraceGVN("Instruction %d kills\n", instr->id());
@@ -3203,7 +3207,7 @@
}
Handle<GlobalObject> global(info()->global_object());
global->Lookup(*var->name(), lookup);
- if (!lookup->IsProperty() ||
+ if (!lookup->IsFound() ||
lookup->type() != NORMAL ||
(is_store && lookup->IsReadOnly()) ||
lookup->holder() != *global) {
@@ -3548,7 +3552,7 @@
Handle<String> name,
LookupResult* lookup) {
type->LookupInDescriptors(NULL, *name, lookup);
- if (!lookup->IsPropertyOrTransition()) return false;
+ if (!lookup->IsFound()) return false;
if (lookup->type() == FIELD) return true;
return (lookup->type() == MAP_TRANSITION) &&
(type->unused_property_fields() > 0);
@@ -3597,7 +3601,7 @@
instr->set_transition(transition);
// TODO(fschneider): Record the new map type of the object in the IR to
// enable elimination of redundant checks after the transition store.
- instr->SetFlag(HValue::kChangesMaps);
+ instr->SetGVNFlag(kChangesMaps);
}
return instr;
}
@@ -4155,13 +4159,13 @@
Handle<String> name) {
LookupResult lookup(isolate());
map->LookupInDescriptors(NULL, *name, &lookup);
- if (lookup.IsProperty() && lookup.type() == FIELD) {
+ if (lookup.IsFound() && lookup.type() == FIELD) {
return BuildLoadNamedField(obj,
expr,
map,
&lookup,
true);
- } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
+ } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) {
AddInstruction(new(zone()) HCheckNonSmi(obj));
AddInstruction(new(zone()) HCheckMap(obj, map, NULL,
ALLOW_ELEMENT_TRANSITION_MAPS));
@@ -6249,7 +6253,7 @@
Handle<GlobalObject> global(info()->global_object());
LookupResult lookup(isolate());
global->Lookup(*name, &lookup);
- if (lookup.IsProperty() &&
+ if (lookup.IsFound() &&
lookup.type() == NORMAL &&
lookup.GetValue()->IsJSFunction()) {
Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 9705859..b77e975 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -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:
@@ -1056,10 +1056,10 @@
Resize(kInitialSize);
}
- void Kill(int flags);
+ void Kill(GVNFlagSet flags);
void Add(HValue* value) {
- present_flags_ |= value->flags();
+ present_flags_.Add(value->gvn_flags());
Insert(value);
}
@@ -1092,7 +1092,8 @@
int array_size_;
int lists_size_;
int count_; // The number of values stored in the HValueMap.
- int present_flags_; // All flags that are in any value in the HValueMap.
+ GVNFlagSet present_flags_; // All flags that are in any value in the
+ // HValueMap.
HValueMapListElement* array_; // Primary store - contains the first value
// with a given hash. Colliding elements are stored in linked lists.
HValueMapListElement* lists_; // The linked lists containing hash collisions.
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 82bb02a..bb1d678 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -473,7 +473,6 @@
Counters* counters = isolate->counters();
__ IncrementCounter(counters->keyed_load_generic_smi(), 1);
__ ret(0);
-
__ bind(&check_number_dictionary);
__ mov(ebx, eax);
__ SmiUntag(ebx);
@@ -535,15 +534,25 @@
__ mov(edi, FieldOperand(eax, String::kHashFieldOffset));
__ shr(edi, String::kHashShift);
__ xor_(ecx, edi);
- __ and_(ecx, KeyedLookupCache::kCapacityMask);
+ __ and_(ecx, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
// Load the key (consisting of map and symbol) from the cache and
// check for match.
+ Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(masm->isolate());
__ mov(edi, ecx);
__ shl(edi, kPointerSizeLog2 + 1);
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
+ __ j(not_equal, &try_second_entry);
+ __ add(edi, Immediate(kPointerSize));
+ __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
+ __ j(equal, &hit_on_first_entry);
+
+ __ bind(&try_second_entry);
+ __ lea(edi, Operand(ecx, 1));
+ __ shl(edi, kPointerSizeLog2 + 1);
+ __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &slow);
__ add(edi, Immediate(kPointerSize));
__ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
@@ -556,6 +565,18 @@
// ecx : lookup cache index
ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
+
+ // Hit on second entry.
+ __ add(ecx, Immediate(1));
+ __ mov(edi,
+ Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
+ __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
+ __ sub(edi, ecx);
+ __ j(above_equal, &property_array_property);
+ __ jmp(&load_in_object_property);
+
+ // Hit on first entry.
+ __ bind(&hit_on_first_entry);
__ mov(edi,
Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
@@ -563,6 +584,7 @@
__ j(above_equal, &property_array_property);
// Load in-object property.
+ __ bind(&load_in_object_property);
__ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
__ add(ecx, edi);
__ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index a5c96b0..976b234 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -2216,7 +2216,7 @@
Handle<String> name) {
LookupResult lookup(isolate());
type->LookupInDescriptors(NULL, *name, &lookup);
- ASSERT(lookup.IsProperty() &&
+ ASSERT(lookup.IsFound() &&
(lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
if (lookup.type() == FIELD) {
int index = lookup.GetLocalFieldIndexFromMap(*type);
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 0adb101..f6f4241 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -1053,7 +1053,7 @@
// and CALLBACKS, so inline only them, other cases may be added
// later.
bool compile_followup_inline = false;
- if (lookup->IsProperty() && lookup->IsCacheable()) {
+ if (lookup->IsFound() && lookup->IsCacheable()) {
if (lookup->type() == FIELD) {
compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS &&
diff --git a/src/ic.cc b/src/ic.cc
index 4361ba2..b084109 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -860,7 +860,7 @@
}
PropertyAttributes attr;
- if (lookup.IsProperty() &&
+ if (lookup.IsFound() &&
(lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
// Get the property.
Handle<Object> result =
@@ -1083,7 +1083,7 @@
}
PropertyAttributes attr;
- if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
+ if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
// Get the property.
Handle<Object> result =
Object::GetProperty(object, object, &lookup, name, &attr);
@@ -1206,10 +1206,12 @@
static bool StoreICableLookup(LookupResult* lookup) {
// Bail out if we didn't find a result.
- if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false;
+ if (!lookup->IsFound() || lookup->type() == NULL_DESCRIPTOR) return false;
- // If the property is read-only, we leave the IC in its current
- // state.
+ // Bail out if inline caching is not allowed.
+ if (!lookup->IsCacheable()) return false;
+
+ // If the property is read-only, we leave the IC in its current state.
if (lookup->IsReadOnly()) return false;
return true;
diff --git a/src/isolate.h b/src/isolate.h
index 89793f8..7e6807b 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1071,6 +1071,7 @@
Isolate* previous_isolate;
EntryStackItem* previous_item;
+ private:
DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
};
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 96f406f..289e6b8 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -4252,7 +4252,7 @@
const Register inline_site = t5;
const Register scratch = a2;
- const int32_t kDeltaToLoadBoolResult = 4 * kPointerSize;
+ const int32_t kDeltaToLoadBoolResult = 5 * kPointerSize;
Label slow, loop, is_instance, is_not_instance, not_js_object;
@@ -4296,11 +4296,12 @@
// Patch the (relocated) inlined map check.
// The offset was stored in t0 safepoint slot.
- // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal)
+ // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal).
__ LoadFromSafepointRegisterSlot(scratch, t0);
__ Subu(inline_site, ra, scratch);
- // Patch the relocated value to map.
- __ PatchRelocatedValue(inline_site, scratch, map);
+ // Get the map location in scratch and patch it.
+ __ GetRelocatedValue(inline_site, scratch, v1); // v1 used as scratch.
+ __ sw(map, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
}
// Register mapping: a3 is object map and t0 is function prototype.
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc
index 8e78488..d974f08 100644
--- a/src/mips/ic-mips.cc
+++ b/src/mips/ic-mips.cc
@@ -1033,19 +1033,26 @@
__ lw(t0, FieldMemOperand(a0, String::kHashFieldOffset));
__ sra(at, t0, String::kHashShift);
__ xor_(a3, a3, at);
- __ And(a3, a3, Operand(KeyedLookupCache::kCapacityMask));
+ int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
+ __ And(a3, a3, Operand(mask));
// Load the key (consisting of map and symbol) from the cache and
// check for match.
+ Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(isolate);
__ li(t0, Operand(cache_keys));
__ sll(at, a3, kPointerSizeLog2 + 1);
__ addu(t0, t0, at);
- __ lw(t1, MemOperand(t0)); // Move t0 to symbol.
- __ Addu(t0, t0, Operand(kPointerSize));
- __ Branch(&slow, ne, a2, Operand(t1));
__ lw(t1, MemOperand(t0));
+ __ Branch(&try_second_entry, ne, a2, Operand(t1));
+ __ lw(t1, MemOperand(t0, kPointerSize));
+ __ Branch(&hit_on_first_entry, eq, a0, Operand(t1));
+
+ __ bind(&try_second_entry);
+ __ lw(t1, MemOperand(t0, kPointerSize * 2));
+ __ Branch(&slow, ne, a2, Operand(t1));
+ __ lw(t1, MemOperand(t0, kPointerSize * 3));
__ Branch(&slow, ne, a0, Operand(t1));
// Get field offset.
@@ -1055,6 +1062,19 @@
// a3 : lookup cache index
ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(isolate);
+
+ // Hit on second entry.
+ __ li(t0, Operand(cache_field_offsets));
+ __ sll(at, a3, kPointerSizeLog2);
+ __ addu(at, t0, at);
+ __ lw(t1, MemOperand(at, kPointerSize));
+ __ lbu(t2, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
+ __ Subu(t1, t1, t2);
+ __ Branch(&property_array_property, ge, t1, Operand(zero_reg));
+ __ Branch(&load_in_object_property);
+
+ // Hit on first entry.
+ __ bind(&hit_on_first_entry);
__ li(t0, Operand(cache_field_offsets));
__ sll(at, a3, kPointerSizeLog2);
__ addu(at, t0, at);
@@ -1064,6 +1084,7 @@
__ Branch(&property_array_property, ge, t1, Operand(zero_reg));
// Load in-object property.
+ __ bind(&load_in_object_property);
__ lbu(t2, FieldMemOperand(a2, Map::kInstanceSizeOffset));
__ addu(t2, t2, t1); // Index from start of object.
__ Subu(a1, a1, Operand(kHeapObjectTag)); // Remove the heap tag.
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 0f31c2a..7a230c1 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -2019,7 +2019,10 @@
// We use Factory::the_hole_value() on purpose instead of loading from the
// root array to force relocation to be able to later patch with
// the cached map.
- __ li(at, Operand(factory()->the_hole_value()), true);
+ Handle<JSGlobalPropertyCell> cell =
+ factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
+ __ li(at, Operand(Handle<Object>(cell)));
+ __ lw(at, FieldMemOperand(at, JSGlobalPropertyCell::kValueOffset));
__ Branch(&cache_miss, ne, map, Operand(at));
// We use Factory::the_hole_value() on purpose instead of loading from the
// root array to force relocation to be able to later patch
@@ -2266,7 +2269,7 @@
Handle<String> name) {
LookupResult lookup(isolate());
type->LookupInDescriptors(NULL, *name, &lookup);
- ASSERT(lookup.IsProperty() &&
+ ASSERT(lookup.IsFound() &&
(lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
if (lookup.type() == FIELD) {
int index = lookup.GetLocalFieldIndexFromMap(*type);
@@ -2716,7 +2719,7 @@
this, pointers, Safepoint::kLazyDeopt);
// The number of arguments is stored in receiver which is a0, as expected
// by InvokeFunction.
- v8::internal::ParameterCount actual(receiver);
+ ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD);
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@@ -2772,31 +2775,41 @@
int arity,
LInstruction* instr,
CallKind call_kind) {
- // Change context if needed.
- bool change_context =
- (info()->closure()->context() != function->context()) ||
- scope()->contains_with() ||
- (scope()->num_heap_slots() > 0);
- if (change_context) {
- __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
- }
-
- // Set a0 to arguments count if adaption is not needed. Assumes that a0
- // is available to write to at this point.
- if (!function->NeedsArgumentsAdaption()) {
- __ li(a0, Operand(arity));
- }
+ bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
+ function->shared()->formal_parameter_count() == arity;
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
- // Invoke function.
- __ SetCallKind(t1, call_kind);
- __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
- __ Call(at);
+ if (can_invoke_directly) {
+ __ LoadHeapObject(a1, function);
+ // Change context if needed.
+ bool change_context =
+ (info()->closure()->context() != function->context()) ||
+ scope()->contains_with() ||
+ (scope()->num_heap_slots() > 0);
+ if (change_context) {
+ __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
+ }
- // Set up deoptimization.
- RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
+ // Set r0 to arguments count if adaption is not needed. Assumes that r0
+ // is available to write to at this point.
+ if (!function->NeedsArgumentsAdaption()) {
+ __ li(a0, Operand(arity));
+ }
+
+ // Invoke function.
+ __ SetCallKind(t1, call_kind);
+ __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
+ __ Call(at);
+
+ // Set up deoptimization.
+ RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
+ } else {
+ SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
+ ParameterCount count(arity);
+ __ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
+ }
// Restore context.
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@@ -2806,7 +2819,6 @@
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(v0));
__ mov(a0, v0);
- __ LoadHeapObject(a1, instr->function());
CallKnownFunction(instr->function(), instr->arity(), instr, CALL_AS_METHOD);
}
@@ -3249,7 +3261,6 @@
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(v0));
- __ LoadHeapObject(a1, instr->target());
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
}
@@ -4095,16 +4106,26 @@
}
+void LCodeGen::DoCheckMapCommon(Register reg,
+ Register scratch,
+ Handle<Map> map,
+ CompareMapMode mode,
+ LEnvironment* env) {
+ Label success;
+ __ CompareMapAndBranch(reg, scratch, map, &success, eq, &success, mode);
+ DeoptimizeIf(al, env);
+ __ bind(&success);
+}
+
+
void LCodeGen::DoCheckMap(LCheckMap* instr) {
Register scratch = scratch0();
LOperand* input = instr->InputAt(0);
ASSERT(input->IsRegister());
Register reg = ToRegister(input);
- __ lw(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
- DeoptimizeIf(ne,
- instr->environment(),
- scratch,
- Operand(instr->hydrogen()->map()));
+ Handle<Map> map = instr->hydrogen()->map();
+ DoCheckMapCommon(reg, scratch, map, instr->hydrogen()->mode(),
+ instr->environment());
}
@@ -4172,11 +4193,9 @@
// Check prototype maps up to the holder.
while (!current_prototype.is_identical_to(holder)) {
- __ lw(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset));
- DeoptimizeIf(ne,
- instr->environment(),
- temp2,
- Operand(Handle<Map>(current_prototype->map())));
+ DoCheckMapCommon(temp1, temp2,
+ Handle<Map>(current_prototype->map()),
+ ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
current_prototype =
Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
// Load next prototype object.
@@ -4184,11 +4203,9 @@
}
// Check the holder map.
- __ lw(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset));
- DeoptimizeIf(ne,
- instr->environment(),
- temp2,
- Operand(Handle<Map>(current_prototype->map())));
+ DoCheckMapCommon(temp1, temp2,
+ Handle<Map>(current_prototype->map()),
+ ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
}
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index e90fc4c..513992c 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -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:
@@ -115,6 +115,9 @@
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check);
+ void DoCheckMapCommon(Register reg, Register scratch, Handle<Map> map,
+ CompareMapMode mode, LEnvironment* env);
+
// Parallel move support.
void DoParallelMove(LParallelMove* move);
void DoGap(LGap* instr);
@@ -223,8 +226,8 @@
Safepoint::DeoptMode mode);
void DeoptimizeIf(Condition cc,
LEnvironment* environment,
- Register src1,
- const Operand& src2);
+ Register src1 = zero_reg,
+ const Operand& src2 = Operand(zero_reg));
void AddToTranslation(Translation* translation,
LOperand* op,
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 141d2a8..941c7fe 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -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:
@@ -3315,17 +3315,51 @@
}
+void MacroAssembler::CompareMapAndBranch(Register obj,
+ Register scratch,
+ Handle<Map> map,
+ Label* early_success,
+ Condition cond,
+ Label* branch_to,
+ CompareMapMode mode) {
+ lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
+ Operand right = 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) {
+ Branch(early_success, eq, scratch, right);
+ right = 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) {
+ Branch(early_success, eq, scratch, right);
+ right = Operand(Handle<Map>(transitioned_double_map));
+ }
+ }
+
+ Branch(branch_to, cond, scratch, right);
+}
+
+
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);
}
- lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
- li(at, Operand(map));
- Branch(fail, ne, scratch, Operand(at));
+ Label success;
+ CompareMapAndBranch(obj, scratch, map, &success, ne, fail, mode);
+ bind(&success);
}
@@ -3432,10 +3466,12 @@
Handle<Code> code_constant,
Register code_reg,
Label* done,
+ bool* definitely_mismatches,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) {
bool definitely_matches = false;
+ *definitely_mismatches = false;
Label regular_invoke;
// Check whether the expected and actual arguments count match. If not,
@@ -3466,6 +3502,7 @@
// arguments.
definitely_matches = true;
} else {
+ *definitely_mismatches = true;
li(a2, Operand(expected.immediate()));
}
}
@@ -3489,7 +3526,9 @@
SetCallKind(t1, call_kind);
Call(adaptor);
call_wrapper.AfterCall();
- jmp(done);
+ if (!*definitely_mismatches) {
+ Branch(done);
+ }
} else {
SetCallKind(t1, call_kind);
Jump(adaptor, RelocInfo::CODE_TARGET);
@@ -3510,21 +3549,25 @@
Label done;
- InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag,
+ bool definitely_mismatches = false;
+ InvokePrologue(expected, actual, Handle<Code>::null(), code,
+ &done, &definitely_mismatches, flag,
call_wrapper, call_kind);
- if (flag == CALL_FUNCTION) {
- call_wrapper.BeforeCall(CallSize(code));
- SetCallKind(t1, call_kind);
- Call(code);
- call_wrapper.AfterCall();
- } else {
- ASSERT(flag == JUMP_FUNCTION);
- SetCallKind(t1, call_kind);
- Jump(code);
+ if (!definitely_mismatches) {
+ if (flag == CALL_FUNCTION) {
+ call_wrapper.BeforeCall(CallSize(code));
+ SetCallKind(t1, call_kind);
+ Call(code);
+ call_wrapper.AfterCall();
+ } else {
+ ASSERT(flag == JUMP_FUNCTION);
+ SetCallKind(t1, call_kind);
+ Jump(code);
+ }
+ // Continue here if InvokePrologue does handle the invocation due to
+ // mismatched parameter counts.
+ bind(&done);
}
- // Continue here if InvokePrologue does handle the invocation due to
- // mismatched parameter counts.
- bind(&done);
}
@@ -3539,18 +3582,22 @@
Label done;
- InvokePrologue(expected, actual, code, no_reg, &done, flag,
+ bool definitely_mismatches = false;
+ InvokePrologue(expected, actual, code, no_reg,
+ &done, &definitely_mismatches, flag,
NullCallWrapper(), call_kind);
- if (flag == CALL_FUNCTION) {
- SetCallKind(t1, call_kind);
- Call(code, rmode);
- } else {
- SetCallKind(t1, call_kind);
- Jump(code, rmode);
+ if (!definitely_mismatches) {
+ if (flag == CALL_FUNCTION) {
+ SetCallKind(t1, call_kind);
+ Call(code, rmode);
+ } else {
+ SetCallKind(t1, call_kind);
+ Jump(code, rmode);
+ }
+ // Continue here if InvokePrologue does handle the invocation due to
+ // mismatched parameter counts.
+ bind(&done);
}
- // Continue here if InvokePrologue does handle the invocation due to
- // mismatched parameter counts.
- bind(&done);
}
@@ -3583,6 +3630,7 @@
void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& actual,
InvokeFlag flag,
+ const CallWrapper& call_wrapper,
CallKind call_kind) {
// You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame());
@@ -3596,7 +3644,7 @@
// allow recompilation to take effect without changing any of the
// call sites.
lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
- InvokeCode(a3, expected, actual, flag, NullCallWrapper(), call_kind);
+ InvokeCode(a3, expected, actual, flag, call_wrapper, call_kind);
}
@@ -4733,6 +4781,34 @@
FlushICache(li_location, 2);
}
+void MacroAssembler::GetRelocatedValue(Register li_location,
+ Register value,
+ Register scratch) {
+ lw(value, MemOperand(li_location));
+ if (emit_debug_code()) {
+ And(value, value, kOpcodeMask);
+ Check(eq, "The instruction should be a lui.",
+ value, Operand(LUI));
+ lw(value, MemOperand(li_location));
+ }
+
+ // value now holds a lui instruction. Extract the immediate.
+ sll(value, value, kImm16Bits);
+
+ lw(scratch, MemOperand(li_location, kInstrSize));
+ if (emit_debug_code()) {
+ And(scratch, scratch, kOpcodeMask);
+ Check(eq, "The instruction should be an ori.",
+ scratch, Operand(ORI));
+ lw(scratch, MemOperand(li_location, kInstrSize));
+ }
+ // "scratch" now holds an ori instruction. Extract the immediate.
+ andi(scratch, scratch, kImm16Mask);
+
+ // Merge the results.
+ or_(value, value, scratch);
+}
+
void MacroAssembler::CheckPageFlag(
Register object,
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index cdcee00..b976f6e 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -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:
@@ -820,6 +820,7 @@
void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& actual,
InvokeFlag flag,
+ const CallWrapper& call_wrapper,
CallKind call_kind);
@@ -930,15 +931,29 @@
Register scratch4,
Label* fail);
- // Check if the map of an object is equal to a specified map (either
- // given directly or as an index into the root list) and branch to
- // label if not. Skip the smi check if not required (object is known
- // to be a heap object).
+ // Compare an object's map with the specified map and its transitioned
+ // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Jumps to
+ // "branch_to" if the result of the comparison is "cond". If multiple map
+ // compares are required, the compare sequences branches to early_success.
+ void CompareMapAndBranch(Register obj,
+ Register scratch,
+ Handle<Map> map,
+ Label* early_success,
+ Condition cond,
+ Label* branch_to,
+ CompareMapMode mode = REQUIRE_EXACT_MAP);
+
+ // Check if the map of an object is equal to a specified map and branch to
+ // label if not. Skip the smi check if not required (object is known to be a
+ // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
+ // against maps that are ElementsKind transition maps of the specificed map.
void CheckMap(Register obj,
Register scratch,
Handle<Map> map,
Label* fail,
- SmiCheckType smi_check_type);
+ SmiCheckType smi_check_type,
+ CompareMapMode mode = REQUIRE_EXACT_MAP);
+
void CheckMap(Register obj,
Register scratch,
@@ -1327,6 +1342,10 @@
void PatchRelocatedValue(Register li_location,
Register scratch,
Register new_value);
+ // Get the relocatad value (loaded data) from the lui/ori pair.
+ void GetRelocatedValue(Register li_location,
+ Register value,
+ Register scratch);
private:
void CallCFunctionHelper(Register function,
@@ -1359,6 +1378,7 @@
Handle<Code> code_constant,
Register code_reg,
Label* done,
+ bool* definitely_mismatches,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind);
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 97a58c7..0051edf 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -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:
@@ -377,13 +377,9 @@
Label* miss_label) {
// a0 : value.
Label exit;
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver_reg, miss_label, scratch);
-
- // Check that the map of the receiver hasn't changed.
- __ lw(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
- __ Branch(miss_label, ne, scratch, Operand(Handle<Map>(object->map())));
+ // Check that the map of the object hasn't changed.
+ __ CheckMap(receiver_reg, scratch, Handle<Map>(object->map()), miss_label,
+ DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
if (object->IsJSGlobalProxy()) {
@@ -747,7 +743,7 @@
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(optimization.constant_function(), arguments_,
- JUMP_FUNCTION, call_kind);
+ JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
// Deferred code for fast API call case---clean preallocated space.
@@ -1037,9 +1033,8 @@
__ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
} else {
Handle<Map> current_map(current->map());
- __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
- // Branch on the result of the map check.
- __ Branch(miss, ne, scratch1, Operand(current_map));
+ __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK,
+ ALLOW_ELEMENT_TRANSITION_MAPS);
// Check access rights to the global object. This has to happen after
// the map check so that we know that the object is actually a global
// object.
@@ -1070,8 +1065,8 @@
LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1));
// Check the holder map.
- __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
- __ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map())));
+ __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss,
+ DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform security check for access to the global object.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
@@ -1209,7 +1204,7 @@
// and CALLBACKS, so inline only them, other cases may be added
// later.
bool compile_followup_inline = false;
- if (lookup->IsProperty() && lookup->IsCacheable()) {
+ if (lookup->IsFound() && lookup->IsCacheable()) {
if (lookup->type() == FIELD) {
compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS &&
@@ -1934,7 +1929,8 @@
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
- __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
+ __ InvokeFunction(
+ function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// a2: function name.
@@ -2067,7 +2063,8 @@
__ bind(&slow);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
- __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
+ __ InvokeFunction(
+ function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// a2: function name.
@@ -2167,7 +2164,8 @@
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
- __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
+ __ InvokeFunction(
+ function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// a2: function name.
@@ -2346,7 +2344,8 @@
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
- __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind);
+ __ InvokeFunction(
+ function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
@@ -2493,12 +2492,9 @@
// -----------------------------------
Label miss;
- // Check that the object isn't a smi.
- __ JumpIfSmi(a1, &miss);
-
// Check that the map of the object hasn't changed.
- __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset));
- __ Branch(&miss, ne, a3, Operand(Handle<Map>(object->map())));
+ __ CheckMap(a1, a3, Handle<Map>(object->map()), &miss,
+ DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
if (object->IsJSGlobalProxy()) {
@@ -2540,12 +2536,9 @@
// -----------------------------------
Label miss;
- // Check that the object isn't a smi.
- __ JumpIfSmi(a1, &miss);
-
// Check that the map of the object hasn't changed.
- __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset));
- __ Branch(&miss, ne, a3, Operand(Handle<Map>(receiver->map())));
+ __ CheckMap(a1, a3, Handle<Map>(receiver->map()), &miss,
+ DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) {
diff --git a/src/objects.cc b/src/objects.cc
index 0941e79..426327c 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -4353,7 +4353,7 @@
current != heap->null_value() && current->IsJSObject();
current = JSObject::cast(current)->GetPrototype()) {
JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
- if (result->IsProperty() && result->type() == CALLBACKS) return;
+ if (result->IsFound() && result->type() == CALLBACKS) return;
}
result->NotFound();
}
@@ -4457,7 +4457,7 @@
// Lookup the name.
LookupResult result(heap->isolate());
LocalLookupRealNamedProperty(name, &result);
- if (result.IsProperty()) {
+ if (result.IsFound()) {
// TODO(mstarzinger): We should check for result.IsDontDelete() here once
// we only call into the runtime once to set both getter and setter.
if (result.type() == CALLBACKS) {
@@ -4935,75 +4935,191 @@
}
-void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
- // Traverse the transition tree without using a stack. We do this by
- // reversing the pointers in the maps and descriptor arrays.
- Map* current = this;
- Map* meta_map = GetHeap()->meta_map();
- Object** map_or_index_field = NULL;
- while (current != meta_map) {
- DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
- *RawField(current, Map::kInstanceDescriptorsOrBitField3Offset));
- if (!d->IsEmpty()) {
- FixedArray* contents = reinterpret_cast<FixedArray*>(
- d->get(DescriptorArray::kContentArrayIndex));
- map_or_index_field = RawField(contents, HeapObject::kMapOffset);
- Object* map_or_index = *map_or_index_field;
- bool map_done = true; // Controls a nested continue statement.
- for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0;
- i < contents->length();
- i += 2) {
- PropertyDetails details(Smi::cast(contents->get(i + 1)));
- if (details.IsTransition()) {
- // Found a map in the transition array. We record our progress in
- // the transition array by recording the current map in the map field
- // of the next map and recording the index in the transition array in
- // the map field of the array.
- Map* next = Map::cast(contents->get(i));
- next->set_map_no_write_barrier(current);
- *map_or_index_field = Smi::FromInt(i + 2);
- current = next;
- map_done = false;
- break;
- }
- }
- if (!map_done) continue;
- } else {
- map_or_index_field = NULL;
- }
- // That was the regular transitions, now for the prototype transitions.
- FixedArray* prototype_transitions =
- current->unchecked_prototype_transitions();
- Object** proto_map_or_index_field =
- RawField(prototype_transitions, HeapObject::kMapOffset);
- Object* map_or_index = *proto_map_or_index_field;
- const int start = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
- int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : start;
- if (i < prototype_transitions->length()) {
- // Found a map in the prototype transition array. Record progress in
- // an analogous way to the regular transitions array above.
- Object* perhaps_map = prototype_transitions->get(i);
- if (perhaps_map->IsMap()) {
- Map* next = Map::cast(perhaps_map);
- next->set_map_no_write_barrier(current);
- *proto_map_or_index_field =
- Smi::FromInt(i + kProtoTransitionElementsPerEntry);
- current = next;
- continue;
- }
- }
- *proto_map_or_index_field = GetHeap()->fixed_array_map();
- if (map_or_index_field != NULL) {
- *map_or_index_field = GetHeap()->fixed_array_map();
- }
+// An iterator over all map transitions in an descriptor array, reusing the map
+// field of the contens array while it is running.
+class IntrusiveMapTransitionIterator {
+ public:
+ explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array)
+ : descriptor_array_(descriptor_array) { }
- // The callback expects a map to have a real map as its map, so we save
- // the map field, which is being used to track the traversal and put the
- // correct map (the meta_map) in place while we do the callback.
- Map* prev = current->map();
- current->set_map_no_write_barrier(meta_map);
- callback(current, data);
- current = prev;
+ void Start() {
+ ASSERT(!IsIterating());
+ if (HasContentArray()) *ContentHeader() = Smi::FromInt(0);
+ }
+
+ bool IsIterating() {
+ return HasContentArray() && (*ContentHeader())->IsSmi();
+ }
+
+ Map* Next() {
+ ASSERT(IsIterating());
+ FixedArray* contents = ContentArray();
+ int index = Smi::cast(*ContentHeader())->value();
+ while (index < contents->length()) {
+ int next_index = index + 2;
+ PropertyDetails details(Smi::cast(contents->get(index + 1)));
+ if (details.IsTransition()) {
+ *ContentHeader() = Smi::FromInt(next_index);
+ return static_cast<Map*>(contents->get(index));
+ }
+ index = next_index;
+ }
+ *ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map();
+ return NULL;
+ }
+
+ private:
+ bool HasContentArray() {
+ return descriptor_array_-> length() > DescriptorArray::kContentArrayIndex;
+ }
+
+ FixedArray* ContentArray() {
+ Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex);
+ return static_cast<FixedArray*>(array);
+ }
+
+ Object** ContentHeader() {
+ return HeapObject::RawField(ContentArray(), DescriptorArray::kMapOffset);
+ }
+
+ DescriptorArray* descriptor_array_;
+};
+
+
+// An iterator over all prototype transitions, reusing the map field of the
+// underlying array while it is running.
+class IntrusivePrototypeTransitionIterator {
+ public:
+ explicit IntrusivePrototypeTransitionIterator(FixedArray* proto_trans)
+ : proto_trans_(proto_trans) { }
+
+ void Start() {
+ ASSERT(!IsIterating());
+ if (HasTransitions()) *Header() = Smi::FromInt(0);
+ }
+
+ bool IsIterating() {
+ return HasTransitions() && (*Header())->IsSmi();
+ }
+
+ Map* Next() {
+ ASSERT(IsIterating());
+ int transitionNumber = Smi::cast(*Header())->value();
+ if (transitionNumber < NumberOfTransitions()) {
+ *Header() = Smi::FromInt(transitionNumber + 1);
+ return GetTransition(transitionNumber);
+ }
+ *Header() = proto_trans_->GetHeap()->fixed_array_map();
+ return NULL;
+ }
+
+ private:
+ bool HasTransitions() {
+ return proto_trans_->length() >= Map::kProtoTransitionHeaderSize;
+ }
+
+ Object** Header() {
+ return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset);
+ }
+
+ int NumberOfTransitions() {
+ Object* num = proto_trans_->get(Map::kProtoTransitionNumberOfEntriesOffset);
+ return Smi::cast(num)->value();
+ }
+
+ Map* GetTransition(int transitionNumber) {
+ return Map::cast(proto_trans_->get(IndexFor(transitionNumber)));
+ }
+
+ int IndexFor(int transitionNumber) {
+ return Map::kProtoTransitionHeaderSize +
+ Map::kProtoTransitionMapOffset +
+ transitionNumber * Map::kProtoTransitionElementsPerEntry;
+ }
+
+ FixedArray* proto_trans_;
+};
+
+
+// To traverse the transition tree iteratively, we have to store two kinds of
+// information in a map: The parent map in the traversal and which children of a
+// node have already been visited. To do this without additional memory, we
+// temporarily reuse two maps with known values:
+//
+// (1) The map of the map temporarily holds the parent, and is restored to the
+// meta map afterwards.
+//
+// (2) The info which children have already been visited depends on which part
+// of the map we currently iterate:
+//
+// (a) If we currently follow normal map transitions, we temporarily store
+// the current index in the map of the FixedArray of the desciptor
+// array's contents, and restore it to the fixed array map afterwards.
+// Note that a single descriptor can have 0, 1, or 2 transitions.
+//
+// (b) If we currently follow prototype transitions, we temporarily store
+// the current index in the map of the FixedArray holding the prototype
+// transitions, and restore it to the fixed array map afterwards.
+//
+// Note that the child iterator is just a concatenation of two iterators: One
+// iterating over map transitions and one iterating over prototype transisitons.
+class TraversableMap : public Map {
+ public:
+ // Record the parent in the traversal within this map. Note that this destroys
+ // this map's map!
+ void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
+
+ // Reset the current map's map, returning the parent previously stored in it.
+ TraversableMap* GetAndResetParent() {
+ TraversableMap* old_parent = static_cast<TraversableMap*>(map());
+ set_map_no_write_barrier(GetHeap()->meta_map());
+ return old_parent;
+ }
+
+ // Start iterating over this map's children, possibly destroying a FixedArray
+ // map (see explanation above).
+ void ChildIteratorStart() {
+ IntrusiveMapTransitionIterator(instance_descriptors()).Start();
+ IntrusivePrototypeTransitionIterator(
+ unchecked_prototype_transitions()).Start();
+ }
+
+ // If we have an unvisited child map, return that one and advance. If we have
+ // none, return NULL and reset any destroyed FixedArray maps.
+ TraversableMap* ChildIteratorNext() {
+ IntrusiveMapTransitionIterator descriptor_iterator(instance_descriptors());
+ if (descriptor_iterator.IsIterating()) {
+ Map* next = descriptor_iterator.Next();
+ if (next != NULL) return static_cast<TraversableMap*>(next);
+ }
+ IntrusivePrototypeTransitionIterator
+ proto_iterator(unchecked_prototype_transitions());
+ if (proto_iterator.IsIterating()) {
+ Map* next = proto_iterator.Next();
+ if (next != NULL) return static_cast<TraversableMap*>(next);
+ }
+ return NULL;
+ }
+};
+
+
+// Traverse the transition tree in postorder without using the C++ stack by
+// doing pointer reversal.
+void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
+ TraversableMap* current = static_cast<TraversableMap*>(this);
+ current->ChildIteratorStart();
+ while (true) {
+ TraversableMap* child = current->ChildIteratorNext();
+ if (child != NULL) {
+ child->ChildIteratorStart();
+ child->SetParent(current);
+ current = child;
+ } else {
+ TraversableMap* parent = current->GetAndResetParent();
+ callback(current, data);
+ if (current == this) break;
+ current = parent;
+ }
}
}
@@ -7472,7 +7588,7 @@
LookupResult result(heap->isolate());
String* name = GetThisPropertyAssignmentName(i);
js_object->LocalLookupRealNamedProperty(name, &result);
- if (result.IsProperty() && result.type() == CALLBACKS) {
+ if (result.IsFound() && result.type() == CALLBACKS) {
return false;
}
}
@@ -10146,7 +10262,7 @@
LookupResult result(isolate);
LocalLookupRealNamedProperty(key, &result);
- return result.IsProperty() && (result.type() == CALLBACKS);
+ return result.IsFound() && (result.type() == CALLBACKS);
}
diff --git a/src/objects.h b/src/objects.h
index 0d5bec5..f2e35a6 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -7806,7 +7806,8 @@
static const int kTagOffset = HeapObject::kHeaderSize;
static const int kPropertyListOffset = kTagOffset + kPointerSize;
static const int kHeaderSize = kPropertyListOffset + kPointerSize;
- protected:
+
+ private:
DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
};
diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc
index f4c20ae..c27e3c9 100644
--- a/src/platform-cygwin.cc
+++ b/src/platform-cygwin.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-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:
@@ -722,6 +722,7 @@
static Mutex* mutex_;
static SamplerThread* instance_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SamplerThread);
};
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 65bd720..6d04fb1 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 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:
@@ -840,6 +840,7 @@
static bool signal_handler_installed_;
static struct sigaction old_signal_handler_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SignalSender);
};
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 5a1c0d1..30b6086 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -1178,6 +1178,7 @@
static bool signal_handler_installed_;
static struct sigaction old_signal_handler_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SignalSender);
};
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index 369c3e4..9f8fe12 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -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:
@@ -854,6 +854,7 @@
static Mutex* mutex_;
static SamplerThread* instance_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SamplerThread);
};
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index a01c08d..fda5fb4 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -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:
@@ -923,6 +923,7 @@
static bool signal_handler_installed_;
static struct sigaction old_signal_handler_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SignalSender);
};
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index 08bec93..9b3713f 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -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:
@@ -53,6 +53,7 @@
#include "v8.h"
#include "platform.h"
+#include "v8threads.h"
#include "vm-state-inl.h"
@@ -322,43 +323,126 @@
static const int kMmapFdOffset = 0;
+VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
+
VirtualMemory::VirtualMemory(size_t size) {
- address_ = mmap(NULL, size, PROT_NONE,
- MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
- kMmapFd, kMmapFdOffset);
+ address_ = ReserveRegion(size);
size_ = size;
}
+VirtualMemory::VirtualMemory(size_t size, size_t alignment)
+ : address_(NULL), size_(0) {
+ ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
+ size_t request_size = RoundUp(size + alignment,
+ static_cast<intptr_t>(OS::AllocateAlignment()));
+ void* reservation = mmap(OS::GetRandomMmapAddr(),
+ request_size,
+ PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+ kMmapFd,
+ kMmapFdOffset);
+ if (reservation == MAP_FAILED) return;
+
+ Address base = static_cast<Address>(reservation);
+ Address aligned_base = RoundUp(base, alignment);
+ ASSERT_LE(base, aligned_base);
+
+ // Unmap extra memory reserved before and after the desired block.
+ if (aligned_base != base) {
+ size_t prefix_size = static_cast<size_t>(aligned_base - base);
+ OS::Free(base, prefix_size);
+ request_size -= prefix_size;
+ }
+
+ size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
+ ASSERT_LE(aligned_size, request_size);
+
+ if (aligned_size != request_size) {
+ size_t suffix_size = request_size - aligned_size;
+ OS::Free(aligned_base + aligned_size, suffix_size);
+ request_size -= suffix_size;
+ }
+
+ ASSERT(aligned_size == request_size);
+
+ address_ = static_cast<void*>(aligned_base);
+ size_ = aligned_size;
+}
+
+
VirtualMemory::~VirtualMemory() {
if (IsReserved()) {
- if (0 == munmap(address(), size())) address_ = MAP_FAILED;
+ bool result = ReleaseRegion(address(), size());
+ ASSERT(result);
+ USE(result);
}
}
bool VirtualMemory::IsReserved() {
- return address_ != MAP_FAILED;
+ return address_ != NULL;
}
-bool VirtualMemory::Commit(void* address, size_t size, bool executable) {
- int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0);
- if (MAP_FAILED == mmap(address, size, prot,
- MAP_PRIVATE | MAP_ANON | MAP_FIXED,
- kMmapFd, kMmapFdOffset)) {
- return false;
- }
+void VirtualMemory::Reset() {
+ address_ = NULL;
+ size_ = 0;
+}
- UpdateAllocatedSpaceLimits(address, size);
- return true;
+
+bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
+ return CommitRegion(address, size, is_executable);
}
bool VirtualMemory::Uncommit(void* address, size_t size) {
- return mmap(address, size, PROT_NONE,
- MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED,
- kMmapFd, kMmapFdOffset) != MAP_FAILED;
+ return UncommitRegion(address, size);
+}
+
+
+void* VirtualMemory::ReserveRegion(size_t size) {
+ void* result = mmap(OS::GetRandomMmapAddr(),
+ size,
+ PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+ kMmapFd,
+ kMmapFdOffset);
+
+ if (result == MAP_FAILED) return NULL;
+
+ return result;
+}
+
+
+bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
+ int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+ if (MAP_FAILED == mmap(base,
+ size,
+ prot,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+ kMmapFd,
+ kMmapFdOffset)) {
+ return false;
+ }
+
+ UpdateAllocatedSpaceLimits(base, size);
+ return true;
+}
+
+
+bool VirtualMemory::UncommitRegion(void* base, size_t size) {
+ return mmap(base,
+ size,
+ PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED,
+ kMmapFd,
+ kMmapFdOffset) != MAP_FAILED;
+}
+
+
+bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
+ return munmap(base, size) == 0;
}
@@ -759,6 +843,7 @@
static bool signal_handler_installed_;
static struct sigaction old_signal_handler_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SignalSender);
};
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 5c000e6..ffda660 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -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:
@@ -2006,6 +2006,7 @@
static Mutex* mutex_;
static SamplerThread* instance_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SamplerThread);
};
diff --git a/src/property.h b/src/property.h
index 3203dd1..120734d 100644
--- a/src/property.h
+++ b/src/property.h
@@ -265,11 +265,6 @@
return IsFound() && GetPropertyDetails().IsProperty();
}
- // Is the result a property or a transition?
- bool IsPropertyOrTransition() {
- return IsFound() && (type() != NULL_DESCRIPTOR);
- }
-
bool IsCacheable() { return cacheable_; }
void DisallowCaching() { cacheable_ = false; }
diff --git a/src/runtime.cc b/src/runtime.cc
index b9ec719..2bac304 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1434,7 +1434,7 @@
!object->IsJSContextExtensionObject()) {
LookupResult lookup(isolate);
object->Lookup(*name, &lookup);
- if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) {
+ if (lookup.IsFound() && (lookup.type() == CALLBACKS)) {
return ThrowRedeclarationError(isolate, "const", name);
}
}
@@ -1482,7 +1482,7 @@
JSObject::cast(object)->map()->is_hidden_prototype()) {
JSObject* raw_holder = JSObject::cast(object);
raw_holder->LocalLookup(*name, &lookup);
- if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
+ if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
HandleScope handle_scope(isolate);
Handle<JSObject> holder(raw_holder);
PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
@@ -1648,7 +1648,7 @@
// GetProperty() to get the current value as it 'unholes' the value.
LookupResult lookup(isolate);
object->LocalLookupRealNamedProperty(*name, &lookup);
- ASSERT(lookup.IsProperty()); // the property was declared
+ ASSERT(lookup.IsFound()); // the property was declared
ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
PropertyType type = lookup.type();
@@ -1869,9 +1869,19 @@
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
- NoHandleAllocation handle_free;
ASSERT(args.length() == 1);
- CONVERT_CHECKED(JSFunction, function, args[0]);
+ CONVERT_CHECKED(JSReceiver, callable, args[0]);
+
+ if (!callable->IsJSFunction()) {
+ HandleScope scope(isolate);
+ bool threw = false;
+ Handle<Object> delegate =
+ Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
+ if (threw) return Failure::Exception();
+ callable = JSFunction::cast(*delegate);
+ }
+ JSFunction* function = JSFunction::cast(callable);
+
SharedFunctionInfo* shared = function->shared();
if (shared->native() || !shared->is_classic_mode()) {
return isolate->heap()->undefined_value();
@@ -4246,7 +4256,7 @@
// appropriate.
LookupResult result(isolate);
receiver->LocalLookup(key, &result);
- if (result.IsProperty() && result.type() == FIELD) {
+ if (result.IsFound() && result.type() == FIELD) {
int offset = result.GetFieldIndex();
keyed_lookup_cache->Update(receiver_map, key, offset);
return receiver->FastPropertyAt(offset);
@@ -4394,7 +4404,7 @@
js_object->LocalLookupRealNamedProperty(*name, &result);
// Special case for callback properties.
- if (result.IsProperty() && result.type() == CALLBACKS) {
+ if (result.IsFound() && result.type() == CALLBACKS) {
Object* callback = result.GetCallbackObject();
// To be compatible with Safari we do not change the value on API objects
// in Object.defineProperty(). Firefox disagrees here, and actually changes
diff --git a/src/serialize.h b/src/serialize.h
index 6efb8ee..839bfc5 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2009 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:
@@ -581,6 +581,7 @@
friend class ObjectSerializer;
friend class Deserializer;
+ private:
DISALLOW_COPY_AND_ASSIGN(Serializer);
};
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index ec8f6bd..c7f4f94 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -1452,13 +1452,13 @@
CallOptimization::CallOptimization(LookupResult* lookup) {
- if (!lookup->IsProperty() ||
- !lookup->IsCacheable() ||
- lookup->type() != CONSTANT_FUNCTION) {
- Initialize(Handle<JSFunction>::null());
- } else {
+ if (lookup->IsFound() &&
+ lookup->IsCacheable() &&
+ lookup->type() == CONSTANT_FUNCTION) {
// We only optimize constant function calls.
Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
+ } else {
+ Initialize(Handle<JSFunction>::null());
}
}
diff --git a/src/utils.h b/src/utils.h
index 17bf06f..1d40c98 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -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:
@@ -931,9 +931,17 @@
explicit EnumSet(T bits = 0) : bits_(bits) {}
bool IsEmpty() const { return bits_ == 0; }
bool Contains(E element) const { return (bits_ & Mask(element)) != 0; }
+ bool ContainsAnyOf(const EnumSet& set) const {
+ return (bits_ & set.bits_) != 0;
+ }
void Add(E element) { bits_ |= Mask(element); }
+ void Add(const EnumSet& set) { bits_ |= set.bits_; }
void Remove(E element) { bits_ &= ~Mask(element); }
+ void Remove(const EnumSet& set) { bits_ &= ~set.bits_; }
+ void RemoveAll() { bits_ = 0; }
+ void Intersect(const EnumSet& set) { bits_ &= set.bits_; }
T ToIntegral() const { return bits_; }
+ bool operator==(const EnumSet& set) { return bits_ == set.bits_; }
private:
T Mask(E element) const {
diff --git a/src/version.cc b/src/version.cc
index 2c1daeb..ba531ab 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 8
-#define BUILD_NUMBER 7
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 8
+#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index 0204460..8dca1e1 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -462,23 +462,43 @@
__ movl(rdi, FieldOperand(rax, String::kHashFieldOffset));
__ shr(rdi, Immediate(String::kHashShift));
__ xor_(rcx, rdi);
- __ and_(rcx, Immediate(KeyedLookupCache::kCapacityMask));
+ int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
+ __ and_(rcx, Immediate(mask));
// Load the key (consisting of map and symbol) from the cache and
// check for match.
+ Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys
= ExternalReference::keyed_lookup_cache_keys(masm->isolate());
__ movq(rdi, rcx);
__ shl(rdi, Immediate(kPointerSizeLog2 + 1));
__ LoadAddress(kScratchRegister, cache_keys);
__ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, 0));
- __ j(not_equal, &slow);
+ __ j(not_equal, &try_second_entry);
__ cmpq(rax, Operand(kScratchRegister, rdi, times_1, kPointerSize));
+ __ j(equal, &hit_on_first_entry);
+
+ __ bind(&try_second_entry);
+ __ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, kPointerSize * 2));
+ __ j(not_equal, &slow);
+ __ cmpq(rax, Operand(kScratchRegister, rdi, times_1, kPointerSize * 3));
__ j(not_equal, &slow);
// Get field offset, which is a 32-bit integer.
ExternalReference cache_field_offsets
= ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
+
+ // Hit on second entry.
+ __ LoadAddress(kScratchRegister, cache_field_offsets);
+ __ addl(rcx, Immediate(1));
+ __ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
+ __ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
+ __ subq(rdi, rcx);
+ __ j(above_equal, &property_array_property);
+ __ jmp(&load_in_object_property);
+
+ // Hit on first entry.
+ __ bind(&hit_on_first_entry);
__ LoadAddress(kScratchRegister, cache_field_offsets);
__ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
__ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
@@ -486,6 +506,7 @@
__ j(above_equal, &property_array_property);
// Load in-object property.
+ __ bind(&load_in_object_property);
__ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
__ addq(rcx, rdi);
__ movq(rax, FieldOperand(rdx, rcx, times_pointer_size, 0));
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 350ff6f..e051214 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -2142,7 +2142,7 @@
Handle<String> name) {
LookupResult lookup(isolate());
type->LookupInDescriptors(NULL, *name, &lookup);
- ASSERT(lookup.IsProperty() &&
+ ASSERT(lookup.IsFound() &&
(lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
if (lookup.type() == FIELD) {
int index = lookup.GetLocalFieldIndexFromMap(*type);
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 47c2177..a6e1b83 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -1045,7 +1045,7 @@
// and CALLBACKS, so inline only them, other cases may be added
// later.
bool compile_followup_inline = false;
- if (lookup->IsProperty() && lookup->IsCacheable()) {
+ if (lookup->IsFound() && lookup->IsCacheable()) {
if (lookup->type() == FIELD) {
compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS &&