@@ -5849,12 +5849,6 @@ class Script: public Struct {
// [type]: the script type.
DECL_ACCESSORS(type, Smi)

// [compilation]: how the the script was compiled.
DECL_ACCESSORS(compilation_type, Smi)

// [is_compiled]: determines whether the script has already been compiled.
DECL_ACCESSORS(compilation_state, Smi)

// [line_ends]: FixedArray of line ends positions.
DECL_ACCESSORS(line_ends, Object)

@@ -5866,6 +5860,19 @@ class Script: public Struct {
// function from which eval was called where eval was called.
DECL_ACCESSORS(eval_from_instructions_offset, Smi)

// [flags]: Holds an exciting bitfield.
DECL_ACCESSORS(flags, Smi)

// [compilation_type]: how the the script was compiled. Encoded in the
// 'flags' field.
inline CompilationType compilation_type();
inline void set_compilation_type(CompilationType type);

// [compilation_state]: determines whether the script has already been
// compiled. Encoded in the 'flags' field.
inline CompilationState compilation_state();
inline void set_compilation_state(CompilationState state);

static inline Script* cast(Object* obj);

// If script source is an external string, check that the underlying
@@ -5884,17 +5891,20 @@ class Script: public Struct {
static const int kContextOffset = kDataOffset + kPointerSize;
static const int kWrapperOffset = kContextOffset + kPointerSize;
static const int kTypeOffset = kWrapperOffset + kPointerSize;
static const int kCompilationTypeOffset = kTypeOffset + kPointerSize;
static const int kCompilationStateOffset =
kCompilationTypeOffset + kPointerSize;
static const int kLineEndsOffset = kCompilationStateOffset + kPointerSize;
static const int kLineEndsOffset = kTypeOffset + kPointerSize;
static const int kIdOffset = kLineEndsOffset + kPointerSize;
static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
static const int kEvalFrominstructionsOffsetOffset =
kEvalFromSharedOffset + kPointerSize;
static const int kSize = kEvalFrominstructionsOffsetOffset + kPointerSize;
static const int kFlagsOffset =
kEvalFrominstructionsOffsetOffset + kPointerSize;
static const int kSize = kFlagsOffset + kPointerSize;

private:
// Bit positions in the flags field.
static const int kCompilationTypeBit = 0;
static const int kCompilationStateBit = 1;

DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
};

@@ -60,23 +60,12 @@ void OptimizingCompilerThread::Run() {
OS::Sleep(FLAG_parallel_recompilation_delay);
}

switch (static_cast<StopFlag>(Acquire_Load(&stop_thread_))) {
case CONTINUE:
break;
case STOP:
if (FLAG_trace_parallel_recompilation) {
time_spent_total_ = OS::Ticks() - epoch;
}
stop_semaphore_->Signal();
return;
case FLUSH:
// Reset input queue semaphore.
delete input_queue_semaphore_;
input_queue_semaphore_ = OS::CreateSemaphore(0);
// Signal for main thread to start flushing.
stop_semaphore_->Signal();
// Return to start of consumer loop.
continue;
if (Acquire_Load(&stop_thread_)) {
stop_semaphore_->Signal();
if (FLAG_trace_parallel_recompilation) {
time_spent_total_ = OS::Ticks() - epoch;
}
return;
}

int64_t compiling_start = 0;
@@ -113,41 +102,9 @@ void OptimizingCompilerThread::CompileNext() {
}


void OptimizingCompilerThread::FlushQueue(
UnboundQueue<OptimizingCompiler*>* queue,
bool restore_function_code) {
ASSERT(!IsOptimizerThread());
OptimizingCompiler* optimizing_compiler;
// The optimizing compiler is allocated in the CompilationInfo's zone.
while (queue->Dequeue(&optimizing_compiler)) {
CompilationInfo* info = optimizing_compiler->info();
if (restore_function_code) {
Handle<JSFunction> function = info->closure();
function->ReplaceCode(function->shared()->code());
}
delete info;
}
}


void OptimizingCompilerThread::Flush() {
ASSERT(!IsOptimizerThread());
Release_Store(&stop_thread_, static_cast<AtomicWord>(FLUSH));
input_queue_semaphore_->Signal();

FlushQueue(&input_queue_, true);
NoBarrier_Store(&queue_length_, static_cast<AtomicWord>(0));

stop_semaphore_->Wait();
Release_Store(&stop_thread_, static_cast<AtomicWord>(CONTINUE));

FlushQueue(&output_queue_, true);
}


void OptimizingCompilerThread::Stop() {
ASSERT(!IsOptimizerThread());
Release_Store(&stop_thread_, static_cast<AtomicWord>(STOP));
Release_Store(&stop_thread_, static_cast<AtomicWord>(true));
input_queue_semaphore_->Signal();
stop_semaphore_->Wait();

@@ -157,8 +114,14 @@ void OptimizingCompilerThread::Stop() {
while (NoBarrier_Load(&queue_length_) > 0) CompileNext();
InstallOptimizedFunctions();
} else {
FlushQueue(&input_queue_, false);
FlushQueue(&output_queue_, false);
OptimizingCompiler* optimizing_compiler;
// The optimizing compiler is allocated in the CompilationInfo's zone.
while (input_queue_.Dequeue(&optimizing_compiler)) {
delete optimizing_compiler->info();
}
while (output_queue_.Dequeue(&optimizing_compiler)) {
delete optimizing_compiler->info();
}
}

if (FLAG_trace_parallel_recompilation) {
@@ -54,13 +54,13 @@ class OptimizingCompilerThread : public Thread {
install_mutex_(OS::CreateMutex()),
time_spent_compiling_(0),
time_spent_total_(0) {
NoBarrier_Store(&stop_thread_, static_cast<AtomicWord>(CONTINUE));
NoBarrier_Store(&stop_thread_, static_cast<AtomicWord>(false));
NoBarrier_Store(&queue_length_, static_cast<AtomicWord>(0));
}

void Run();
void Stop();
void Flush();
void CompileNext();
void QueueForOptimization(OptimizingCompiler* optimizing_compiler);
void InstallOptimizedFunctions();

@@ -92,12 +92,6 @@ class OptimizingCompilerThread : public Thread {
}

private:
enum StopFlag { CONTINUE, STOP, FLUSH };

void FlushQueue(UnboundQueue<OptimizingCompiler*>* queue,
bool restore_function_code);
void CompileNext();

#ifdef DEBUG
int thread_id_;
Mutex* thread_id_mutex_;
@@ -892,7 +892,7 @@ size_t OS::AllocateAlignment() {
}


static void* GetRandomAddr() {
void* OS::GetRandomMmapAddr() {
Isolate* isolate = Isolate::UncheckedCurrent();
// Note that the current isolate isn't set up in a call path via
// CpuFeatures::Probe. We don't care about randomization in this case because
@@ -925,7 +925,7 @@ static void* RandomizedVirtualAlloc(size_t size, int action, int protection) {
if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) {
// For exectutable pages try and randomize the allocation address
for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) {
base = VirtualAlloc(GetRandomAddr(), size, action, protection);
base = VirtualAlloc(OS::GetRandomMmapAddr(), size, action, protection);
}
}

@@ -372,19 +372,30 @@ void ProfileTree::ShortPrint() {
}


CpuProfile::CpuProfile(const char* title, unsigned uid, bool record_samples)
: title_(title),
uid_(uid),
record_samples_(record_samples),
start_time_ms_(OS::TimeCurrentMillis()),
end_time_ms_(0) {
}


void CpuProfile::AddPath(const Vector<CodeEntry*>& path) {
ProfileNode* top_frame_node = top_down_.AddPathFromEnd(path);
if (record_samples_) samples_.Add(top_frame_node);
}


void CpuProfile::CalculateTotalTicks() {
void CpuProfile::CalculateTotalTicksAndSamplingRate() {
end_time_ms_ = OS::TimeCurrentMillis();
top_down_.CalculateTotalTicks();
}


void CpuProfile::SetActualSamplingRate(double actual_sampling_rate) {
top_down_.SetTickRatePerMs(actual_sampling_rate);
double duration = end_time_ms_ - start_time_ms_;
if (duration < 1) duration = 1;
unsigned ticks = top_down_.root()->total_ticks();
double rate = ticks / duration;
top_down_.SetTickRatePerMs(rate);
}


@@ -529,8 +540,7 @@ bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid,
}


CpuProfile* CpuProfilesCollection::StopProfiling(const char* title,
double actual_sampling_rate) {
CpuProfile* CpuProfilesCollection::StopProfiling(const char* title) {
const int title_len = StrLength(title);
CpuProfile* profile = NULL;
current_profiles_semaphore_->Wait();
@@ -543,8 +553,7 @@ CpuProfile* CpuProfilesCollection::StopProfiling(const char* title,
current_profiles_semaphore_->Signal();

if (profile == NULL) return NULL;
profile->CalculateTotalTicks();
profile->SetActualSamplingRate(actual_sampling_rate);
profile->CalculateTotalTicksAndSamplingRate();
finished_profiles_.Add(profile);
return profile;
}
@@ -601,29 +610,6 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(
}


void SampleRateCalculator::Tick() {
if (--wall_time_query_countdown_ == 0)
UpdateMeasurements(OS::TimeCurrentMillis());
}


void SampleRateCalculator::UpdateMeasurements(double current_time) {
if (measurements_count_++ != 0) {
const double measured_ticks_per_ms =
(kWallTimeQueryIntervalMs * ticks_per_ms_) /
(current_time - last_wall_time_);
// Update the average value.
ticks_per_ms_ +=
(measured_ticks_per_ms - ticks_per_ms_) / measurements_count_;
// Update the externally accessible result.
result_ = static_cast<AtomicWord>(ticks_per_ms_ * kResultScale);
}
last_wall_time_ = current_time;
wall_time_query_countdown_ =
static_cast<unsigned>(kWallTimeQueryIntervalMs * ticks_per_ms_);
}


const char* const ProfileGenerator::kAnonymousFunctionName =
"(anonymous function)";
const char* const ProfileGenerator::kProgramEntryName =
@@ -203,13 +203,11 @@ class ProfileTree {

class CpuProfile {
public:
CpuProfile(const char* title, unsigned uid, bool record_samples)
: title_(title), uid_(uid), record_samples_(record_samples) { }
CpuProfile(const char* title, unsigned uid, bool record_samples);

// Add pc -> ... -> main() call path to the profile.
void AddPath(const Vector<CodeEntry*>& path);
void CalculateTotalTicks();
void SetActualSamplingRate(double actual_sampling_rate);
void CalculateTotalTicksAndSamplingRate();

INLINE(const char* title() const) { return title_; }
INLINE(unsigned uid() const) { return uid_; }
@@ -227,6 +225,8 @@ class CpuProfile {
const char* title_;
unsigned uid_;
bool record_samples_;
double start_time_ms_;
double end_time_ms_;
List<ProfileNode*> samples_;
ProfileTree top_down_;

@@ -286,7 +286,7 @@ class CpuProfilesCollection {
~CpuProfilesCollection();

bool StartProfiling(const char* title, unsigned uid, bool record_samples);
CpuProfile* StopProfiling(const char* title, double actual_sampling_rate);
CpuProfile* StopProfiling(const char* title);
List<CpuProfile*>* profiles() { return &finished_profiles_; }
const char* GetName(Name* name) {
return function_and_resource_names_.GetName(name);
@@ -329,44 +329,6 @@ class CpuProfilesCollection {
};


class SampleRateCalculator {
public:
SampleRateCalculator()
: result_(Logger::kSamplingIntervalMs * kResultScale),
ticks_per_ms_(Logger::kSamplingIntervalMs),
measurements_count_(0),
wall_time_query_countdown_(1) {
}

double ticks_per_ms() {
return result_ / static_cast<double>(kResultScale);
}
void Tick();
void UpdateMeasurements(double current_time);

// Instead of querying current wall time each tick,
// we use this constant to control query intervals.
static const unsigned kWallTimeQueryIntervalMs = 100;

private:
// As the result needs to be accessed from a different thread, we
// use type that guarantees atomic writes to memory. There should
// be <= 1000 ticks per second, thus storing a value of a 10 ** 5
// order should provide enough precision while keeping away from a
// potential overflow.
static const int kResultScale = 100000;

AtomicWord result_;
// All other fields are accessed only from the sampler thread.
double ticks_per_ms_;
unsigned measurements_count_;
unsigned wall_time_query_countdown_;
double last_wall_time_;

DISALLOW_COPY_AND_ASSIGN(SampleRateCalculator);
};


class ProfileGenerator {
public:
explicit ProfileGenerator(CpuProfilesCollection* profiles);
@@ -375,11 +337,6 @@ class ProfileGenerator {

INLINE(CodeMap* code_map()) { return &code_map_; }

INLINE(void Tick()) { sample_rate_calc_.Tick(); }
INLINE(double actual_sampling_rate()) {
return sample_rate_calc_.ticks_per_ms();
}

static const char* const kAnonymousFunctionName;
static const char* const kProgramEntryName;
static const char* const kGarbageCollectorEntryName;
@@ -395,7 +352,6 @@ class ProfileGenerator {
CodeEntry* program_entry_;
CodeEntry* gc_entry_;
CodeEntry* unresolved_entry_;
SampleRateCalculator sample_rate_calc_;

DISALLOW_COPY_AND_ASSIGN(ProfileGenerator);
};
@@ -408,11 +408,6 @@ void RuntimeProfiler::TearDown() {
}


int RuntimeProfiler::SamplerWindowSize() {
return kSamplerWindowSize;
}


// Update the pointers in the sampler window after a GC.
void RuntimeProfiler::UpdateSamplesAfterScavenge() {
for (int i = 0; i < kSamplerWindowSize; i++) {
@@ -49,9 +49,6 @@ class RuntimeProfiler {
void Reset();
void TearDown();

Object** SamplerWindowAddress();
int SamplerWindowSize();

void NotifyICChanged() { any_ic_changed_ = true; }

// Rate limiting support.
@@ -2948,7 +2948,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
JavaScriptFrame* frame = stack_iterator.frame();

ASSERT_EQ(frame->function(), generator_object->function());
ASSERT(frame->function()->is_compiled());

STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0);
STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0);
@@ -5231,40 +5230,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
}


RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) {
SealHandleScope shs(isolate);
RUNTIME_ASSERT(args.length() == 1);
Handle<Object> object = args.at<Object>(0);
if (object->IsJSObject()) {
Handle<JSObject> js_object(Handle<JSObject>::cast(object));
ASSERT(!js_object->map()->is_observed());
ElementsKind new_kind = js_object->HasFastHoleyElements()
? FAST_HOLEY_DOUBLE_ELEMENTS
: FAST_DOUBLE_ELEMENTS;
return TransitionElements(object, new_kind, isolate);
} else {
return *object;
}
}


RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) {
SealHandleScope shs(isolate);
RUNTIME_ASSERT(args.length() == 1);
Handle<Object> object = args.at<Object>(0);
if (object->IsJSObject()) {
Handle<JSObject> js_object(Handle<JSObject>::cast(object));
ASSERT(!js_object->map()->is_observed());
ElementsKind new_kind = js_object->HasFastHoleyElements()
? FAST_HOLEY_ELEMENTS
: FAST_ELEMENTS;
return TransitionElements(object, new_kind, isolate);
} else {
return *object;
}
}


// Set the native flag on the function.
// This is used to decide if we should transform null and undefined
// into the global object when doing call and apply.
@@ -8466,7 +8431,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
}
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
if (FLAG_parallel_recompilation && sync_with_compiler_thread) {
while (function->IsInRecompileQueue() ||
while (function->IsMarkedForParallelRecompilation() ||
function->IsInRecompileQueue() ||
function->IsMarkedForInstallingRecompiledCode()) {
isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
OS::Sleep(50);
@@ -12921,7 +12887,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
RUNTIME_ASSERT(script_wrapper->value()->IsScript());
Handle<Script> script(Script::cast(script_wrapper->value()));

int compilation_state = Smi::cast(script->compilation_state())->value();
int compilation_state = script->compilation_state();
RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
script->set_source(*source);

@@ -463,8 +463,6 @@ namespace internal {
F(HasExternalDoubleElements, 1, 1) \
F(HasFastProperties, 1, 1) \
F(TransitionElementsKind, 2, 1) \
F(TransitionElementsSmiToDouble, 1, 1) \
F(TransitionElementsDoubleToObject, 1, 1) \
F(HaveSameMap, 2, 1)


@@ -665,6 +665,141 @@ bool Serializer::serialization_enabled_ = false;
bool Serializer::too_late_to_enable_now_ = false;


class CodeAddressMap: public CodeEventLogger {
public:
explicit CodeAddressMap(Isolate* isolate)
: isolate_(isolate) {
isolate->logger()->addCodeEventListener(this);
}

virtual ~CodeAddressMap() {
isolate_->logger()->removeCodeEventListener(this);
}

virtual void CodeMoveEvent(Address from, Address to) {
address_to_name_map_.Move(from, to);
}

virtual void CodeDeleteEvent(Address from) {
address_to_name_map_.Remove(from);
}

const char* Lookup(Address address) {
return address_to_name_map_.Lookup(address);
}

private:
class NameMap {
public:
NameMap() : impl_(&PointerEquals) {}

~NameMap() {
for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) {
DeleteArray(static_cast<const char*>(p->value));
}
}

void Insert(Address code_address, const char* name, int name_size) {
HashMap::Entry* entry = FindOrCreateEntry(code_address);
if (entry->value == NULL) {
entry->value = CopyName(name, name_size);
}
}

const char* Lookup(Address code_address) {
HashMap::Entry* entry = FindEntry(code_address);
return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL;
}

void Remove(Address code_address) {
HashMap::Entry* entry = FindEntry(code_address);
if (entry != NULL) {
DeleteArray(static_cast<char*>(entry->value));
RemoveEntry(entry);
}
}

void Move(Address from, Address to) {
if (from == to) return;
HashMap::Entry* from_entry = FindEntry(from);
ASSERT(from_entry != NULL);
void* value = from_entry->value;
RemoveEntry(from_entry);
HashMap::Entry* to_entry = FindOrCreateEntry(to);
ASSERT(to_entry->value == NULL);
to_entry->value = value;
}

private:
static bool PointerEquals(void* lhs, void* rhs) {
return lhs == rhs;
}

static char* CopyName(const char* name, int name_size) {
char* result = NewArray<char>(name_size + 1);
for (int i = 0; i < name_size; ++i) {
char c = name[i];
if (c == '\0') c = ' ';
result[i] = c;
}
result[name_size] = '\0';
return result;
}

HashMap::Entry* FindOrCreateEntry(Address code_address) {
return impl_.Lookup(code_address, ComputePointerHash(code_address), true);
}

HashMap::Entry* FindEntry(Address code_address) {
return impl_.Lookup(code_address,
ComputePointerHash(code_address),
false);
}

void RemoveEntry(HashMap::Entry* entry) {
impl_.Remove(entry->key, entry->hash);
}

HashMap impl_;

DISALLOW_COPY_AND_ASSIGN(NameMap);
};

virtual void LogRecordedBuffer(Code* code,
SharedFunctionInfo*,
const char* name,
int length) {
address_to_name_map_.Insert(code->address(), name, length);
}

NameMap address_to_name_map_;
Isolate* isolate_;
};


CodeAddressMap* Serializer::code_address_map_ = NULL;


void Serializer::Enable() {
if (!serialization_enabled_) {
ASSERT(!too_late_to_enable_now_);
}
if (serialization_enabled_) return;
serialization_enabled_ = true;
i::Isolate* isolate = Isolate::Current();
isolate->InitializeLoggingAndCounters();
code_address_map_ = new CodeAddressMap(isolate);
}


void Serializer::Disable() {
if (!serialization_enabled_) return;
serialization_enabled_ = false;
delete code_address_map_;
code_address_map_ = NULL;
}


Deserializer::Deserializer(SnapshotByteSource* source)
: isolate_(NULL),
source_(source),
@@ -1458,7 +1593,11 @@ void Serializer::ObjectSerializer::Serialize() {
"ObjectSerialization");
sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");

LOG(i::Isolate::Current(),
ASSERT(code_address_map_);
const char* code_name = code_address_map_->Lookup(object_->address());
LOG(serializer_->isolate_,
CodeNameEvent(object_->address(), sink_->Position(), code_name));
LOG(serializer_->isolate_,
SnapshotPositionEvent(object_->address(), sink_->Position()));

// Mark this object as already serialized.
@@ -459,6 +459,8 @@ class SerializationAddressMapper {
};


class CodeAddressMap;

// There can be only one serializer per V8 process.
class Serializer : public SerializerDeserializer {
public:
@@ -472,14 +474,9 @@ class Serializer : public SerializerDeserializer {
return fullness_[space];
}

static void Enable() {
if (!serialization_enabled_) {
ASSERT(!too_late_to_enable_now_);
}
serialization_enabled_ = true;
}
static void Enable();
static void Disable();

static void Disable() { serialization_enabled_ = false; }
// Call this when you have made use of the fact that there is no serialization
// going on.
static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
@@ -589,6 +586,7 @@ class Serializer : public SerializerDeserializer {
friend class Deserializer;

private:
static CodeAddressMap* code_address_map_;
DISALLOW_COPY_AND_ASSIGN(Serializer);
};

@@ -1992,21 +1992,11 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
ElementsKind elements_kind = receiver_map->elements_kind();
if (!transitioned_map.is_null()) {
if (FLAG_compiled_transitions) {
cached_stub = ElementsTransitionAndStoreStub(
elements_kind,
transitioned_map->elements_kind(),
is_js_array,
store_mode_).GetCode(isolate());
} else {
// TODO(bmeurer) Remove this when compiled transitions is enabled
cached_stub = ElementsTransitionAndStorePlatformStub(
elements_kind,
transitioned_map->elements_kind(),
is_js_array,
strict_mode(),
store_mode_).GetCode(isolate());
}
cached_stub = ElementsTransitionAndStoreStub(
elements_kind,
transitioned_map->elements_kind(),
is_js_array,
store_mode_).GetCode(isolate());
} else {
if (FLAG_compiled_keyed_stores &&
(receiver_map->has_fast_elements() ||
@@ -64,10 +64,15 @@ using namespace std;
// To avoid GCC 4.4 compilation warning about hash_map being deprecated.
#define OLD_DEPRECATED __DEPRECATED
#undef __DEPRECATED
#if defined (ANDROID)
#include <hash_map>
using namespace std;
#else
#include <ext/hash_map>
#define __DEPRECATED OLD_DEPRECATED
using namespace __gnu_cxx;
#endif
#define __DEPRECATED OLD_DEPRECATED
#endif

#include <list>

@@ -34,7 +34,7 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 20
#define BUILD_NUMBER 9
#define BUILD_NUMBER 11
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
@@ -1610,55 +1610,6 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm, ICMissMode miss_mode) {
}


void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rbx : target map
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
// Must return the modified receiver in eax.
if (!FLAG_trace_elements_transitions) {
Label fail;
AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS,
FAST_DOUBLE_ELEMENTS);
ElementsTransitionGenerator::GenerateSmiToDouble(masm, mode, &fail);
__ movq(rax, rdx);
__ Ret();
__ bind(&fail);
}

__ pop(rbx);
__ push(rdx);
__ push(rbx); // return address
__ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1);
}


void KeyedStoreIC::GenerateTransitionElementsDoubleToObject(
MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rbx : target map
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
// Must return the modified receiver in eax.
if (!FLAG_trace_elements_transitions) {
Label fail;
AllocationSiteMode mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS,
FAST_ELEMENTS);
ElementsTransitionGenerator::GenerateDoubleToObject(masm, mode, &fail);
__ movq(rax, rdx);
__ Ret();
__ bind(&fail);
}

__ pop(rbx);
__ push(rdx);
__ push(rbx); // return address
__ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1);
}


#undef __


@@ -429,6 +429,13 @@ double LCodeGen::ToDouble(LConstantOperand* op) const {
}


ExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const {
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(constant->HasExternalReferenceValue());
return constant->ExternalReferenceValue();
}


Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
@@ -1453,7 +1460,11 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
break;
case Token::SHL:
if (shift_count != 0) {
__ shll(ToRegister(left), Immediate(shift_count));
if (instr->hydrogen_value()->representation().IsSmi()) {
__ shl(ToRegister(left), Immediate(shift_count));
} else {
__ shll(ToRegister(left), Immediate(shift_count));
}
}
break;
default:
@@ -1519,6 +1530,11 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
}


void LCodeGen::DoConstantE(LConstantE* instr) {
__ LoadAddress(ToRegister(instr->result()), instr->value());
}


void LCodeGen::DoConstantT(LConstantT* instr) {
Handle<Object> value = instr->value();
AllowDeferredHandleDereference smi_check;
@@ -1699,7 +1715,7 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
LOperand* right = instr->right();
ASSERT(left->Equals(instr->result()));
HMathMinMax::Operation operation = instr->hydrogen()->operation();
if (instr->hydrogen()->representation().IsInteger32()) {
if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
Label return_left;
Condition condition = (operation == HMathMinMax::kMathMin)
? less_equal
@@ -1708,17 +1724,26 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
if (right->IsConstantOperand()) {
Immediate right_imm =
Immediate(ToInteger32(LConstantOperand::cast(right)));
ASSERT(!instr->hydrogen_value()->representation().IsSmi());
__ cmpl(left_reg, right_imm);
__ j(condition, &return_left, Label::kNear);
__ movq(left_reg, right_imm);
} else if (right->IsRegister()) {
Register right_reg = ToRegister(right);
__ cmpl(left_reg, right_reg);
if (instr->hydrogen_value()->representation().IsSmi()) {
__ cmpq(left_reg, right_reg);
} else {
__ cmpl(left_reg, right_reg);
}
__ j(condition, &return_left, Label::kNear);
__ movq(left_reg, right_reg);
} else {
Operand right_op = ToOperand(right);
__ cmpl(left_reg, right_op);
if (instr->hydrogen_value()->representation().IsSmi()) {
__ cmpq(left_reg, right_op);
} else {
__ cmpl(left_reg, right_op);
}
__ j(condition, &return_left, Label::kNear);
__ movq(left_reg, right_op);
}
@@ -2676,6 +2701,19 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
HObjectAccess access = instr->hydrogen()->access();
int offset = access.offset();

if (access.IsExternalMemory()) {
Register result = ToRegister(instr->result());
if (instr->object()->IsConstantOperand()) {
ASSERT(result.is(rax));
__ load_rax(ToExternalReference(LConstantOperand::cast(instr->object())));
} else {
Register object = ToRegister(instr->object());
__ movq(result, MemOperand(object, offset));
}
return;
}

Register object = ToRegister(instr->object());
if (FLAG_track_double_fields &&
instr->hydrogen()->representation().IsDouble()) {
@@ -3913,11 +3951,23 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
Representation representation = instr->representation();

Register object = ToRegister(instr->object());

HObjectAccess access = instr->hydrogen()->access();
int offset = access.offset();

if (access.IsExternalMemory()) {
Register value = ToRegister(instr->value());
if (instr->object()->IsConstantOperand()) {
ASSERT(value.is(rax));
LConstantOperand* object = LConstantOperand::cast(instr->object());
__ store_rax(ToExternalReference(object));
} else {
Register object = ToRegister(instr->object());
__ movq(MemOperand(object, offset), value);
}
return;
}

Register object = ToRegister(instr->object());
Handle<Map> transition = instr->transition();

if (FLAG_track_fields && representation.IsSmi()) {
@@ -4275,7 +4325,7 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
ASSERT_NE(instr->temp(), NULL);
__ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
ToRegister(instr->temp()), kDontSaveFPRegs);
} else if (FLAG_compiled_transitions) {
} else {
PushSafepointRegistersScope scope(this);
if (!object_reg.is(rax)) {
__ movq(rax, object_reg);
@@ -4285,28 +4335,6 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
__ CallStub(&stub);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
} else if (IsFastSmiElementsKind(from_kind) &&
IsFastDoubleElementsKind(to_kind)) {
Register fixed_object_reg = ToRegister(instr->temp());
ASSERT(fixed_object_reg.is(rdx));
Register new_map_reg = ToRegister(instr->new_map_temp());
ASSERT(new_map_reg.is(rbx));
__ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT);
__ movq(fixed_object_reg, object_reg);
CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
RelocInfo::CODE_TARGET, instr);
} else if (IsFastDoubleElementsKind(from_kind) &&
IsFastObjectElementsKind(to_kind)) {
Register fixed_object_reg = ToRegister(instr->temp());
ASSERT(fixed_object_reg.is(rdx));
Register new_map_reg = ToRegister(instr->new_map_temp());
ASSERT(new_map_reg.is(rbx));
__ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT);
__ movq(fixed_object_reg, object_reg);
CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
RelocInfo::CODE_TARGET, instr);
} else {
UNREACHABLE();
}
__ bind(&not_applicable);
}
@@ -106,6 +106,7 @@ class LCodeGen BASE_EMBEDDED {
int32_t ToInteger32(LConstantOperand* op) const;
Smi* ToSmi(LConstantOperand* op) const;
double ToDouble(LConstantOperand* op) const;
ExternalReference ToExternalReference(LConstantOperand* op) const;
bool IsTaggedConstant(LConstantOperand* op) const;
Handle<Object> ToHandle(LConstantOperand* op) const;
Operand ToOperand(LOperand* op) const;
@@ -717,19 +717,19 @@ LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {

LInstruction* LChunkBuilder::DoShift(Token::Value op,
HBitwiseBinaryOperation* instr) {
if (instr->representation().IsSmiOrTagged()) {
ASSERT(instr->left()->representation().IsSmiOrTagged());
ASSERT(instr->right()->representation().IsSmiOrTagged());
if (instr->representation().IsTagged()) {
ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged());

LOperand* left = UseFixed(instr->left(), rdx);
LOperand* right = UseFixed(instr->right(), rax);
LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
return MarkAsCall(DefineFixed(result, rax), instr);
}

ASSERT(instr->representation().IsInteger32());
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
ASSERT(instr->representation().IsSmiOrInteger32());
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* left = UseRegisterAtStart(instr->left());

HValue* right_value = instr->right();
@@ -1562,9 +1562,9 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
LOperand* left = NULL;
LOperand* right = NULL;
if (instr->representation().IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
if (instr->representation().IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
left = UseRegisterAtStart(instr->BetterLeftOperand());
right = UseOrConstantAtStart(instr->BetterRightOperand());
} else {
@@ -1997,6 +1997,8 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
} else if (r.IsDouble()) {
LOperand* temp = TempRegister();
return DefineAsRegister(new(zone()) LConstantD(temp));
} else if (r.IsExternal()) {
return DefineAsRegister(new(zone()) LConstantE);
} else if (r.IsTagged()) {
return DefineAsRegister(new(zone()) LConstantT);
} else {
@@ -2074,6 +2076,10 @@ LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {


LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
if (instr->access().IsExternalMemory() && instr->access().offset() == 0) {
LOperand* obj = UseRegisterOrConstantAtStart(instr->object());
return DefineFixed(new(zone()) LLoadNamedField(obj), rax);
}
LOperand* obj = UseRegisterAtStart(instr->object());
return DefineAsRegister(new(zone()) LLoadNamedField(obj));
}
@@ -2229,19 +2235,10 @@ LInstruction* LChunkBuilder::DoTransitionElementsKind(
LTransitionElementsKind* result =
new(zone()) LTransitionElementsKind(object, new_map_reg, temp_reg);
return result;
} else if (FLAG_compiled_transitions) {
} else {
LTransitionElementsKind* result =
new(zone()) LTransitionElementsKind(object, NULL, NULL);
return AssignPointerMap(result);
} else {
LOperand* object = UseFixed(instr->object(), rax);
LOperand* fixed_object_reg = FixedTemp(rdx);
LOperand* new_map_reg = FixedTemp(rbx);
LTransitionElementsKind* result =
new(zone()) LTransitionElementsKind(object,
new_map_reg,
fixed_object_reg);
return MarkAsCall(result, instr);
}
}

@@ -2258,6 +2255,8 @@ LInstruction* LChunkBuilder::DoTrapAllocationMemento(

LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
bool is_in_object = instr->access().IsInobject();
bool is_external_location = instr->access().IsExternalMemory() &&
instr->access().offset() == 0;
bool needs_write_barrier = instr->NeedsWriteBarrier();
bool needs_write_barrier_for_map = !instr->transition().is_null() &&
instr->NeedsWriteBarrierForMap();
@@ -2267,6 +2266,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
obj = is_in_object
? UseRegister(instr->object())
: UseTempRegister(instr->object());
} else if (is_external_location) {
ASSERT(!is_in_object);
ASSERT(!needs_write_barrier);
ASSERT(!needs_write_barrier_for_map);
obj = UseRegisterOrConstant(instr->object());
} else {
obj = needs_write_barrier_for_map
? UseRegister(instr->object())
@@ -2280,6 +2284,8 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
LOperand* val;
if (needs_write_barrier) {
val = UseTempRegister(instr->value());
} else if (is_external_location) {
val = UseFixed(instr->value(), rax);
} else if (can_be_constant) {
val = UseRegisterOrConstant(instr->value());
} else if (FLAG_track_fields && instr->field_representation().IsSmi()) {
@@ -79,6 +79,7 @@ class LCodeGen;
V(CmpMapAndBranch) \
V(CmpT) \
V(ConstantD) \
V(ConstantE) \
V(ConstantI) \
V(ConstantS) \
V(ConstantT) \
@@ -266,7 +267,7 @@ class LInstruction: public ZoneObject {
bool IsMarkedAsCall() const { return is_call_; }

virtual bool HasResult() const = 0;
virtual LOperand* result() = 0;
virtual LOperand* result() const = 0;

LOperand* FirstInput() { return InputAt(0); }
LOperand* Output() { return HasResult() ? result() : NULL; }
@@ -302,9 +303,9 @@ class LTemplateInstruction: public LInstruction {
public:
// Allow 0 or 1 output operands.
STATIC_ASSERT(R == 0 || R == 1);
virtual bool HasResult() const { return R != 0; }
virtual bool HasResult() const { return R != 0 && result() != NULL; }
void set_result(LOperand* operand) { results_[0] = operand; }
LOperand* result() { return results_[0]; }
LOperand* result() const { return results_[0]; }

protected:
EmbeddedContainer<LOperand*, R> results_;
@@ -1166,6 +1167,17 @@ class LConstantD: public LTemplateInstruction<1, 0, 1> {
};


class LConstantE: public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
DECLARE_HYDROGEN_ACCESSOR(Constant)

ExternalReference value() const {
return hydrogen()->ExternalReferenceValue();
}
};


class LConstantT: public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
@@ -55,6 +55,8 @@ static const bool kLogThreading = false;

using ::v8::AccessorInfo;
using ::v8::Arguments;
using ::v8::Boolean;
using ::v8::BooleanObject;
using ::v8::Context;
using ::v8::Extension;
using ::v8::Function;
@@ -621,6 +623,41 @@ TEST(MakingExternalAsciiStringConditions) {
}


TEST(MakingExternalUnalignedAsciiString) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());

CompileRun("function cons(a, b) { return a + b; }"
"function slice(a) { return a.substring(1); }");
// Create a cons string that will land in old pointer space.
Local<String> cons = Local<String>::Cast(CompileRun(
"cons('abcdefghijklm', 'nopqrstuvwxyz');"));
// Create a sliced string that will land in old pointer space.
Local<String> slice = Local<String>::Cast(CompileRun(
"slice('abcdefghijklmnopqrstuvwxyz');"));

// Trigger GCs so that the newly allocated string moves to old gen.
SimulateFullSpace(HEAP->old_pointer_space());
HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now

// Turn into external string with unaligned resource data.
int dispose_count = 0;
const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
bool success = cons->MakeExternal(
new TestAsciiResource(i::StrDup(c_cons) + 1, &dispose_count));
CHECK(success);
const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
success = slice->MakeExternal(
new TestAsciiResource(i::StrDup(c_slice) + 1, &dispose_count));
CHECK(success);

// Trigger GCs and force evacuation.
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
HEAP->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
}


THREADED_TEST(UsingExternalString) {
i::Factory* factory = i::Isolate::Current()->factory();
{
@@ -1451,13 +1488,13 @@ THREADED_TEST(StringObject) {
CHECK(!not_object->IsStringObject());
v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
CHECK(!as_boxed.IsEmpty());
Local<v8::String> the_string = as_boxed->StringValue();
Local<v8::String> the_string = as_boxed->ValueOf();
CHECK(!the_string.IsEmpty());
ExpectObject("\"test\"", the_string);
v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
CHECK(new_boxed_string->IsStringObject());
as_boxed = new_boxed_string.As<v8::StringObject>();
the_string = as_boxed->StringValue();
the_string = as_boxed->ValueOf();
CHECK(!the_string.IsEmpty());
ExpectObject("\"test\"", the_string);
}
@@ -1474,12 +1511,12 @@ THREADED_TEST(NumberObject) {
CHECK(!boxed_not_number->IsNumberObject());
v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
CHECK(!as_boxed.IsEmpty());
double the_number = as_boxed->NumberValue();
double the_number = as_boxed->ValueOf();
CHECK_EQ(42.0, the_number);
v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
CHECK(new_boxed_number->IsNumberObject());
as_boxed = new_boxed_number.As<v8::NumberObject>();
the_number = as_boxed->NumberValue();
the_number = as_boxed->ValueOf();
CHECK_EQ(43.0, the_number);
}

@@ -1496,16 +1533,68 @@ THREADED_TEST(BooleanObject) {
v8::Handle<v8::BooleanObject> as_boxed =
boxed_boolean.As<v8::BooleanObject>();
CHECK(!as_boxed.IsEmpty());
bool the_boolean = as_boxed->BooleanValue();
bool the_boolean = as_boxed->ValueOf();
CHECK_EQ(true, the_boolean);
v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
CHECK(boxed_true->IsBooleanObject());
CHECK(boxed_false->IsBooleanObject());
as_boxed = boxed_true.As<v8::BooleanObject>();
CHECK_EQ(true, as_boxed->BooleanValue());
CHECK_EQ(true, as_boxed->ValueOf());
as_boxed = boxed_false.As<v8::BooleanObject>();
CHECK_EQ(false, as_boxed->BooleanValue());
CHECK_EQ(false, as_boxed->ValueOf());
}


THREADED_TEST(PrimitiveAndWrappedBooleans) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());

Local<Value> primitive_false = Boolean::New(false);
CHECK(primitive_false->IsBoolean());
CHECK(!primitive_false->IsBooleanObject());
CHECK(!primitive_false->BooleanValue());
CHECK(!primitive_false->IsTrue());
CHECK(primitive_false->IsFalse());

Local<Value> false_value = BooleanObject::New(false);
CHECK(!false_value->IsBoolean());
CHECK(false_value->IsBooleanObject());
CHECK(false_value->BooleanValue());
CHECK(!false_value->IsTrue());
CHECK(!false_value->IsFalse());

Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
CHECK(!false_boolean_object->IsBoolean());
CHECK(false_boolean_object->IsBooleanObject());
// TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
// CHECK(false_boolean_object->BooleanValue());
CHECK(!false_boolean_object->ValueOf());
CHECK(!false_boolean_object->IsTrue());
CHECK(!false_boolean_object->IsFalse());

Local<Value> primitive_true = Boolean::New(true);
CHECK(primitive_true->IsBoolean());
CHECK(!primitive_true->IsBooleanObject());
CHECK(primitive_true->BooleanValue());
CHECK(primitive_true->IsTrue());
CHECK(!primitive_true->IsFalse());

Local<Value> true_value = BooleanObject::New(true);
CHECK(!true_value->IsBoolean());
CHECK(true_value->IsBooleanObject());
CHECK(true_value->BooleanValue());
CHECK(!true_value->IsTrue());
CHECK(!true_value->IsFalse());

Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
CHECK(!true_boolean_object->IsBoolean());
CHECK(true_boolean_object->IsBooleanObject());
// TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
// CHECK(true_boolean_object->BooleanValue());
CHECK(true_boolean_object->ValueOf());
CHECK(!true_boolean_object->IsTrue());
CHECK(!true_boolean_object->IsFalse());
}


@@ -2531,7 +2620,7 @@ THREADED_TEST(SymbolProperties) {
CHECK(sym_obj->Equals(sym2));
CHECK(!sym_obj->StrictEquals(sym2));
CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
CHECK(v8::SymbolObject::Cast(*sym_obj)->SymbolValue()->Equals(sym2));
CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));

// Make sure delete of a non-existent symbol property works.
CHECK(obj->Delete(sym1));
@@ -13139,7 +13228,7 @@ THREADED_TEST(DateAccess) {
v8::HandleScope scope(context->GetIsolate());
v8::Handle<v8::Value> date = v8::Date::New(1224744689038.0);
CHECK(date->IsDate());
CHECK_EQ(1224744689038.0, date.As<v8::Date>()->NumberValue());
CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
}


@@ -222,7 +222,7 @@ TEST(TickEvents) {

processor.StopSynchronously();
processor.Join();
CpuProfile* profile = profiles->StopProfiling("", 1);
CpuProfile* profile = profiles->StopProfiling("");
CHECK_NE(NULL, profile);

// Check call trees.
@@ -286,7 +286,7 @@ TEST(Issue1398) {

processor.StopSynchronously();
processor.Join();
CpuProfile* profile = profiles->StopProfiling("", 1);
CpuProfile* profile = profiles->StopProfiling("");
CHECK_NE(NULL, profile);

int actual_depth = 0;
@@ -77,27 +77,23 @@ class AlwaysOptimizeAllowNativesSyntaxNoInlining {

// Utility class to set --allow-natives-syntax and --nouse-inlining when
// constructed and return to their default state when destroyed.
class AllowNativesSyntaxNoInliningNoParallel {
class AllowNativesSyntaxNoInlining {
public:
AllowNativesSyntaxNoInliningNoParallel()
AllowNativesSyntaxNoInlining()
: allow_natives_syntax_(i::FLAG_allow_natives_syntax),
use_inlining_(i::FLAG_use_inlining),
parallel_recompilation_(i::FLAG_parallel_recompilation) {
use_inlining_(i::FLAG_use_inlining) {
i::FLAG_allow_natives_syntax = true;
i::FLAG_use_inlining = false;
i::FLAG_parallel_recompilation = false;
}

~AllowNativesSyntaxNoInliningNoParallel() {
~AllowNativesSyntaxNoInlining() {
i::FLAG_allow_natives_syntax = allow_natives_syntax_;
i::FLAG_use_inlining = use_inlining_;
i::FLAG_parallel_recompilation = parallel_recompilation_;
}

private:
bool allow_natives_syntax_;
bool use_inlining_;
bool parallel_recompilation_;
};


@@ -347,7 +343,7 @@ TEST(DeoptimizeBinaryOperationADDString) {
const char* f_source = "function f(x, y) { return x + y; };";

{
AllowNativesSyntaxNoInliningNoParallel options;
AllowNativesSyntaxNoInlining options;
// Compile function f and collect to type feedback to insert binary op stub
// call in the optimized code.
i::FLAG_prepare_always_opt = true;
@@ -405,7 +401,7 @@ static void TestDeoptimizeBinaryOpHelper(LocalContext* env,
binary_op);
char* f_source = f_source_buffer.start();

AllowNativesSyntaxNoInliningNoParallel options;
AllowNativesSyntaxNoInlining options;
// Compile function f and collect to type feedback to insert binary op stub
// call in the optimized code.
i::FLAG_prepare_always_opt = true;
@@ -497,7 +493,7 @@ TEST(DeoptimizeCompare) {
const char* f_source = "function f(x, y) { return x < y; };";

{
AllowNativesSyntaxNoInliningNoParallel options;
AllowNativesSyntaxNoInlining options;
// Compile function f and collect to type feedback to insert compare ic
// call in the optimized code.
i::FLAG_prepare_always_opt = true;
@@ -544,7 +540,7 @@ TEST(DeoptimizeLoadICStoreIC) {
const char* g2_source = "function g2(x, y) { x[y] = 1; };";

{
AllowNativesSyntaxNoInliningNoParallel options;
AllowNativesSyntaxNoInlining options;
// Compile functions and collect to type feedback to insert ic
// calls in the optimized code.
i::FLAG_prepare_always_opt = true;
@@ -624,7 +620,7 @@ TEST(DeoptimizeLoadICStoreICNested) {
const char* g2_source = "function g2(x, y) { x[y] = 1; };";

{
AllowNativesSyntaxNoInliningNoParallel options;
AllowNativesSyntaxNoInlining options;
// Compile functions and collect to type feedback to insert ic
// calls in the optimized code.
i::FLAG_prepare_always_opt = true;
@@ -2826,7 +2826,6 @@ void ReleaseStackTraceDataTest(const char* source, const char* accessor) {
// to check whether the data is being released since the external string
// resource's callback is fired when the external string is GC'ed.
FLAG_use_ic = false; // ICs retain objects.
FLAG_parallel_recompilation = false;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
SourceResource* resource = new SourceResource(i::StrDup(source));
@@ -60,7 +60,6 @@ class ScopedLoggerInitializer {
: saved_log_(i::FLAG_log),
saved_prof_lazy_(i::FLAG_prof_lazy),
saved_prof_(i::FLAG_prof),
saved_prof_auto_(i::FLAG_prof_auto),
temp_file_(NULL),
// Need to run this prior to creating the scope.
trick_to_run_init_flags_(init_flags_(prof_lazy)),
@@ -76,7 +75,6 @@ class ScopedLoggerInitializer {
if (temp_file_ != NULL) fclose(temp_file_);
i::FLAG_prof_lazy = saved_prof_lazy_;
i::FLAG_prof = saved_prof_;
i::FLAG_prof_auto = saved_prof_auto_;
i::FLAG_log = saved_log_;
}

@@ -97,15 +95,13 @@ class ScopedLoggerInitializer {
i::FLAG_log = true;
i::FLAG_prof = true;
i::FLAG_prof_lazy = prof_lazy;
i::FLAG_prof_auto = false;
i::FLAG_logfile = i::Log::kLogToTemporaryFile;
return prof_lazy;
}

const bool saved_log_;
const bool saved_prof_lazy_;
const bool saved_prof_;
const bool saved_prof_auto_;
FILE* temp_file_;
const bool trick_to_run_init_flags_;
v8::HandleScope scope_;
@@ -41,7 +41,6 @@ using i::CpuProfilesCollection;
using i::ProfileNode;
using i::ProfileTree;
using i::ProfileGenerator;
using i::SampleRateCalculator;
using i::TickSample;
using i::Vector;

@@ -485,7 +484,7 @@ TEST(RecordTickSample) {
sample3.frames_count = 2;
generator.RecordTickSample(sample3);

CpuProfile* profile = profiles.StopProfiling("", 1);
CpuProfile* profile = profiles.StopProfiling("");
CHECK_NE(NULL, profile);
ProfileTreeTestHelper top_down_test_helper(profile->top_down());
CHECK_EQ(NULL, top_down_test_helper.Walk(entry2));
@@ -505,56 +504,6 @@ TEST(RecordTickSample) {
}


TEST(SampleRateCalculator) {
const double kSamplingIntervalMs = i::Logger::kSamplingIntervalMs;

// Verify that ticking exactly in query intervals results in the
// initial sampling interval.
double time = 0.0;
SampleRateCalculator calc1;
CHECK_EQ(kSamplingIntervalMs, calc1.ticks_per_ms());
calc1.UpdateMeasurements(time);
CHECK_EQ(kSamplingIntervalMs, calc1.ticks_per_ms());
time += SampleRateCalculator::kWallTimeQueryIntervalMs;
calc1.UpdateMeasurements(time);
CHECK_EQ(kSamplingIntervalMs, calc1.ticks_per_ms());
time += SampleRateCalculator::kWallTimeQueryIntervalMs;
calc1.UpdateMeasurements(time);
CHECK_EQ(kSamplingIntervalMs, calc1.ticks_per_ms());
time += SampleRateCalculator::kWallTimeQueryIntervalMs;
calc1.UpdateMeasurements(time);
CHECK_EQ(kSamplingIntervalMs, calc1.ticks_per_ms());

SampleRateCalculator calc2;
time = 0.0;
CHECK_EQ(kSamplingIntervalMs, calc2.ticks_per_ms());
calc2.UpdateMeasurements(time);
CHECK_EQ(kSamplingIntervalMs, calc2.ticks_per_ms());
time += SampleRateCalculator::kWallTimeQueryIntervalMs * 0.5;
calc2.UpdateMeasurements(time);
// (1.0 + 2.0) / 2
CHECK_EQ(kSamplingIntervalMs * 1.5, calc2.ticks_per_ms());
time += SampleRateCalculator::kWallTimeQueryIntervalMs * 0.75;
calc2.UpdateMeasurements(time);
// (1.0 + 2.0 + 2.0) / 3
CHECK_EQ(kSamplingIntervalMs * 5.0, floor(calc2.ticks_per_ms() * 3.0 + 0.5));

SampleRateCalculator calc3;
time = 0.0;
CHECK_EQ(kSamplingIntervalMs, calc3.ticks_per_ms());
calc3.UpdateMeasurements(time);
CHECK_EQ(kSamplingIntervalMs, calc3.ticks_per_ms());
time += SampleRateCalculator::kWallTimeQueryIntervalMs * 2;
calc3.UpdateMeasurements(time);
// (1.0 + 0.5) / 2
CHECK_EQ(kSamplingIntervalMs * 0.75, calc3.ticks_per_ms());
time += SampleRateCalculator::kWallTimeQueryIntervalMs * 1.5;
calc3.UpdateMeasurements(time);
// (1.0 + 0.5 + 0.5) / 3
CHECK_EQ(kSamplingIntervalMs * 2.0, floor(calc3.ticks_per_ms() * 3.0 + 0.5));
}


static void CheckNodeIds(ProfileNode* node, int* expectedId) {
CHECK_EQ((*expectedId)++, node->id());
for (int i = 0; i < node->children()->length(); i++) {
@@ -598,7 +547,7 @@ TEST(SampleIds) {
sample3.frames_count = 2;
generator.RecordTickSample(sample3);

CpuProfile* profile = profiles.StopProfiling("", 1);
CpuProfile* profile = profiles.StopProfiling("");
int nodeId = 1;
CheckNodeIds(profile->top_down()->root(), &nodeId);
CHECK_EQ(7, nodeId - 1);
@@ -627,7 +576,7 @@ TEST(NoSamples) {
sample1.frames_count = 1;
generator.RecordTickSample(sample1);

CpuProfile* profile = profiles.StopProfiling("", 1);
CpuProfile* profile = profiles.StopProfiling("");
int nodeId = 1;
CheckNodeIds(profile->top_down()->root(), &nodeId);
CHECK_EQ(3, nodeId - 1);
@@ -205,7 +205,9 @@ if (support_smi_only_arrays) {

(function literals_after_osr() {
var color = [0];
// Trigger OSR.
while (%GetOptimizationStatus(literals_after_osr, "no sync") == 2) {}
// Trigger OSR, if optimization is not disabled.
if (%GetOptimizationStatus(literals_after_osr) != 4) {
while (%GetOptimizationCount(literals_after_osr) == 0) {}
}
return [color[0]];
})();
@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Flags: --allow-natives-syntax

// Verifies that the KeyedStoreIC correctly handles out-of-bounds stores
// to an array that grow it by a single element. Test functions are
// called twice to make sure that the IC is used, first call is handled
@@ -184,3 +186,24 @@ a = [];
array_store_1(a, 0, 0.5);
assertEquals(0.5, a[0]);
assertEquals(0.5, array_store_1([], 0, 0.5));

// Verify that a grow store will deoptimize if the max gap (difference between
// the end of an array capacity and a new index) is passed. The wrapper is to
// make sure array_store_10 isn't inlined.

(function() {
function grow_store(a,b,c) {
a[b] = c;
}

a = new Array(1);
grow_store(a,1,1);
grow_store(a,2,1);
%OptimizeFunctionOnNextCall(grow_store);
grow_store(a,10,1);
assertOptimized(grow_store);
grow_store(a,2048,1);
assertUnoptimized(grow_store);
%ClearFunctionTypeFeedback(grow_store);
})();

@@ -0,0 +1,76 @@
// Copyright 2013 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.

// Flags: --allow-natives-syntax

function dead1(a, b) {
var x = "a" + "b";
return a; // x, "a", and "b" are dead code
}

function dead2(a, b) {
var x = "0" + a;
var y = "0" + b;
return a; // x and y are both dead
}

function dead3(a, b) {
a = a ? "1" : "0";
b = b ? "1" : "0";
var x = a + "0";
var y = b + "0";
return a; // x and y are both dead
}

function run() {
assertEquals(33, dead1(33, 32));
assertEquals(33, dead2(33, 32));
assertEquals("1", dead3(33, 32));

assertEquals(31, dead1(31, 30));
assertEquals(31, dead2(31, 30));
assertEquals("1", dead3(31, 32));

assertEquals(0, dead1(0, 30));
assertEquals(0, dead2(0, 30));
assertEquals("0", dead3(0, 32));

assertEquals(true, dead1(true, 0));
assertEquals(true, dead2(true, 0));
assertEquals("1", dead3(true, 0));

assertEquals("true", dead1("true", 0));
assertEquals("true", dead2("true", 0));
assertEquals("1", dead3("true", 0));
}

run();
run();
%OptimizeFunctionOnNextCall(dead1);
%OptimizeFunctionOnNextCall(dead2);
%OptimizeFunctionOnNextCall(dead3);
run();
@@ -0,0 +1,65 @@
// Copyright 2013 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.

function dead1(a, b) {
var x = "a" + "b";
return a; // x, "a", and "b" are dead code
}

function dead2(a, b) {
var x = a + "0";
var y = b + "0";
return a; // x and y are both dead
}

function dead3(a, b) {
a = a ? "1" : "0";
b = b ? "1" : "0";
var x = a + "0";
var y = b + "0";
return a; // x and y are both dead
}

assertEquals(33, dead1(33, 32));
assertEquals(33, dead2(33, 32));
assertEquals("1", dead3(33, 32));

assertEquals(31, dead1(31, 30));
assertEquals(31, dead2(31, 30));
assertEquals("1", dead3(31, 32));

assertEquals(0, dead1(0, 30));
assertEquals(0, dead2(0, 30));
assertEquals("0", dead3(0, 32));

assertEquals(true, dead1(true, 0));
assertEquals(true, dead2(true, 0));
assertEquals("1", dead3(true, 0));

assertEquals("true", dead1("true", 0));
assertEquals("true", dead2("true", 0));
assertEquals("1", dead3("true", 0));
@@ -0,0 +1,81 @@
// Copyright 2013 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.

// Flags: --allow-natives-syntax

var S1 = "string1";
var S2 = "@@string2";

function dead1(a, b) {
var x = %StringCharCodeAt(a, 4);
return a; // x is dead code
}

function dead2(a, b) {
var x = %StringCharCodeAt(a, 3);
var y = %StringCharCodeAt(b, 1);
return a; // x and y are both dead
}

function dead3(a, b) {
a = a ? "11" : "12";
b = b ? "13" : "14";
var x = %StringCharCodeAt(a, 2);
var y = %StringCharCodeAt(b, 0);
return a; // x and y are both dead
}

function test() {
var S3 = S1 + S2;

assertEquals(S1, dead1(S1, S2));
assertEquals(S1, dead2(S1, S2));
assertEquals("11", dead3(S1, S2));

assertEquals(S2, dead1(S2, 677));
assertEquals(S2, dead2(S2, S3));
assertEquals("11", dead3(S2, S3));

assertEquals(S3, dead1(S3, 399));
assertEquals(S3, dead2(S3, "false"));
assertEquals("12", dead3(0, 32));

assertEquals(S3, dead1(S3, 0));
assertEquals(S3, dead2(S3, S1));
assertEquals("11", dead3(S3, 0));

assertEquals("true", dead1("true", 0));
assertEquals("true", dead2("true", S3));
assertEquals("11", dead3("true", 0));
}

test();
test();
%OptimizeFunctionOnNextCall(dead1);
%OptimizeFunctionOnNextCall(dead2);
%OptimizeFunctionOnNextCall(dead3);
test();
@@ -0,0 +1,81 @@
// Copyright 2013 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.

// Flags: --allow-natives-syntax

var S1 = "string1";
var S2 = "@@string2";

function dead1(a, b) {
var x = %_StringCharCodeAt(a, 4);
return a; // x is dead code
}

function dead2(a, b) {
var x = %_StringCharCodeAt(a, 3);
var y = %_StringCharCodeAt(b, 1);
return a; // x and y are both dead
}

function dead3(a, b) {
a = a ? "11" : "12";
b = b ? "13" : "14";
var x = %_StringCharCodeAt(a, 2);
var y = %_StringCharCodeAt(b, 0);
return a; // x and y are both dead
}

function test() {
var S3 = S1 + S2;

assertEquals(S1, dead1(S1, S2));
assertEquals(S1, dead2(S1, S2));
assertEquals("11", dead3(S1, S2));

assertEquals(S2, dead1(S2, 677));
assertEquals(S2, dead2(S2, S3));
assertEquals("11", dead3(S2, S3));

assertEquals(S3, dead1(S3, 399));
assertEquals(S3, dead2(S3, "false"));
assertEquals("12", dead3(0, 32));

assertEquals(S3, dead1(S3, 0));
assertEquals(S3, dead2(S3, S1));
assertEquals("11", dead3(S3, 0));

assertEquals("true", dead1("true", 0));
assertEquals("true", dead2("true", S3));
assertEquals("11", dead3("true", 0));
}

test();
test();
%OptimizeFunctionOnNextCall(dead1);
%OptimizeFunctionOnNextCall(dead2);
%OptimizeFunctionOnNextCall(dead3);
test();
@@ -0,0 +1,76 @@
// Copyright 2013 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.

// Flags: --allow-natives-syntax

function dead1(a, b) {
var x = %_StringCharFromCode(a);
return a; // x is dead code
}

function dead2(a, b) {
var x = %_StringCharFromCode(a);
var y = %_StringCharFromCode(b);
return a; // x and y are both dead
}

function dead3(a, b) {
a = a ? 11 : 12;
b = b ? 13 : 14;
var x = %_StringCharFromCode(a);
var y = %_StringCharFromCode(b);
return a; // x and y are both dead
}

function test() {
assertEquals(33, dead1(33, 32));
assertEquals(33, dead2(33, 32));
assertEquals(11, dead3(33, 32));

assertEquals(31, dead1(31, 30));
assertEquals(31, dead2(31, 30));
assertEquals(11, dead3(31, 32));

assertEquals(0, dead1(0, 30));
assertEquals(0, dead2(0, 30));
assertEquals(12, dead3(0, 32));

assertEquals(true, dead1(true, 0));
assertEquals(true, dead2(true, 0));
assertEquals(11, dead3(true, 0));

assertEquals("true", dead1("true", 0));
assertEquals("true", dead2("true", 0));
assertEquals(11, dead3("true", 0));
}

test();
test();
%OptimizeFunctionOnNextCall(dead1);
%OptimizeFunctionOnNextCall(dead2);
%OptimizeFunctionOnNextCall(dead3);
test();
@@ -25,15 +25,15 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Flags: --count-based-interrupts --interrupt-budget=10 --weighted-back-edges
// Flags: --allow-natives-syntax

// Test that OSR works properly when using count-based interrupting/profiling.

function osr_this() {
var a = 1;
// Trigger OSR.
while (%GetOptimizationStatus(osr_this, "no sync") == 2) {}
// Trigger OSR. First check if optimization is disabled.
if (%GetOptimizationStatus(osr_this) == 4) return 1;
while (%GetOptimizationCount(osr_this) == 0) {}
return a;
}
assertEquals(1, osr_this());
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Flags: --compiled-transitions --notrack-allocation-sites
// Flags: --notrack-allocation-sites

function foo(a, v) {
a[0] = v;
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Flags: --allow-natives-syntax --compiled_transitions
// Flags: --allow-natives-syntax

%NeverOptimizeFunction(test);
function test() {
@@ -177,6 +177,21 @@ function crankshaft_test_2() {

run(crankshaft_test_2);

var o = { a: 1, b: 2 };

// Test smi-based Math.min.
function f(o) {
return Math.min(o.a, o.b);
}

assertEquals(1, f(o));
assertEquals(1, f(o));
%OptimizeFunctionOnNextCall(f);
assertEquals(1, f(o));
o.a = 5;
o.b = 4;
assertEquals(4, f(o));

// Test overriding Math.min and Math.max
Math.min = function(a, b) { return a + b; }
Math.max = function(a, b) { return a - b; }
@@ -253,8 +253,3 @@ array-feedback: SKIP

# Deopt every n garbage collections collides with the deopt every n times flag.
regress/regress-2653: SKIP

# Issue 2795:
array-store-and-grow: SKIP if $mode == debug


@@ -52,8 +52,10 @@ function h() {
g();
} else {
// Run for a bit as long as h is unoptimized.
while (%GetOptimizationStatus(h, "no sync") == 2) {
for (var j = 0; j < 100; j++) g();
if (%GetOptimizationStatus(h) != 4) {
while (%GetOptimizationCount(h) == 0) {
for (var j = 0; j < 100; j++) g();
}
}
g();
}
@@ -38,8 +38,7 @@ function f() {
}

f();
assertOptimized(f);

assertTrue(%GetOptimizationCount(f) > 0 || %GetOptimizationStatus(f) == 4);

function g() {
for (var i = 0; i < 1; i++) { }
@@ -70,4 +69,4 @@ function g() {
}

g();
assertOptimized(g);
assertTrue(%GetOptimizationCount(g) > 0 || %GetOptimizationStatus(g) == 4);
@@ -45,8 +45,10 @@

function outer() {
inner(1,2,3);
// Trigger OSR.
while (%GetOptimizationStatus(outer, "no sync") == 2) {}
// Trigger OSR, if optimization is not disabled.
if (%GetOptimizationStatus(outer) != 4) {
while (%GetOptimizationCount(outer) == 0) {}
}
}

outer();
@@ -25,33 +25,21 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Flags: --expose-debug-as debug --allow-natives-syntax
// Flags: --parallel-recompilation-delay=300
// Flags: --allow-natives-syntax

Debug = debug.Debug

function foo() {
var x = 1;
return x;
var a = {
compare_null: function(x) { return null != x; },
kaboom: function() {}
}

function bar() {
var x = 2;
return x;
function crash(x) {
var b = a;
b.compare_null(x) && b.kaboom();
return "ok";
}

foo();
// Mark and trigger parallel optimization.
%OptimizeFunctionOnNextCall(foo, "parallel");
foo();

// Set break points on an unrelated function. This clears both optimized
// and (shared) unoptimized code on foo, and sets both to lazy-compile builtin.
// Clear the break point immediately after to deactivate the debugger.
Debug.setBreakPoint(bar, 0, 0);
Debug.clearAllBreakPoints();

// Install optimized code when parallel optimization finishes.
// This needs to be able to deal with shared code being a builtin.
assertUnoptimized(foo, "sync");

assertEquals("ok", crash(null));
assertEquals("ok", crash(null));
%OptimizeFunctionOnNextCall(crash);
// Used to throw: "TypeError: Cannot call method 'kaboom' of undefined".
assertEquals("ok", crash(1));
@@ -0,0 +1,49 @@
// Copyright 2013 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.

function testPrepareStackTrace(closure) {
var error = undefined;
try {
closure();
assertUnreachable();
} catch (e) {
error = e;
}

// We expect custom formatting to be lazy. Setting the custom
// function right before calling error.stack should be fine.
Error.prepareStackTrace = function(e, frames) {
return "bar";
}

assertEquals("bar", error.stack);
Error.prepareStackTrace = undefined;
}

testPrepareStackTrace(function() { throw new Error("foo"); });
testPrepareStackTrace(function f() { f(); });

@@ -315,7 +315,11 @@ assertTrue(fired);
Error.prepareStackTrace = function() { throw new Error("abc"); };
var message;
try {
throw new Error();
try {
throw new Error();
} catch (e) {
e.stack;
}
} catch (e) {
message = e.message;
}
@@ -324,6 +328,6 @@ assertEquals("abc", message);

// Test that modifying Error.prepareStackTrace by itself works.
Error.prepareStackTrace = function() { Error.prepareStackTrace = "custom"; };
new Error();
new Error().stack;

assertEquals("custom", Error.prepareStackTrace);
@@ -25,8 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Flags: --allow-natives-syntax --compiled-transitions
// Flags: --track-allocation-sites
// Flags: --allow-natives-syntax --track-allocation-sites

// Allocation site for empty double arrays.
function foo() {
@@ -0,0 +1,36 @@
# Copyright 2013 the V8 project authors. All rights reserved.
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. 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.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 test how deep we can recurse, and that we get an exception when we do, as opposed to a stack overflow.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


FAIL msg should be RangeError: Maximum call stack size exceeded.. Was RangeError: Maximum call stack size exceeded.
FAIL msg should be RangeError: Maximum call stack size exceeded.. Was RangeError: Maximum call stack size exceeded.
FAIL msg should be RangeError: Maximum call stack size exceeded.. Was RangeError: Maximum call stack size exceeded.
FAIL msg should be RangeError: Maximum call stack size exceeded.. Was RangeError: Maximum call stack size exceeded.
PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,78 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. 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.
//
// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.

description("This test how deep we can recurse, and that we get an exception when we do, as opposed to a stack overflow.");

function simpleRecursion(depth) {
if (depth)
simpleRecursion(depth - 1);
}

try {
simpleRecursion(17472);
} catch (ex) {
debug("FAIL: " + ex);
}

try {
simpleRecursion(10000000);
} catch (ex) {
var msg = String(eval(ex));
shouldBe("msg", "'RangeError: Maximum call stack size exceeded.'");
}

try {
simpleRecursion(1000000000);
} catch (ex) {
var msg = String(eval(ex));
shouldBe("msg", "'RangeError: Maximum call stack size exceeded.'");
}

var tooFewArgsDepth = 0;

function tooFewArgsRecursion(a) {
if (tooFewArgsDepth) {
tooFewArgsDepth--;
tooFewArgsRecursion();
}
}

try {
tooFewArgsDepth = 10000000;
tooFewArgsRecursion();
} catch (ex) {
var msg = String(eval(ex));
shouldBe("msg", "'RangeError: Maximum call stack size exceeded.'");
}

function tooManyArgsRecursion(depth) {
if (depth)
tooManyArgsRecursion(depth - 1, 1);
}

try {
tooManyArgsRecursion(10000000, 1);
} catch (ex) {
var msg = String(eval(ex));
shouldBe("msg", "'RangeError: Maximum call stack size exceeded.'");
}
@@ -0,0 +1,83 @@
# Copyright 2013 the V8 project authors. All rights reserved.
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. 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.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 test checks toString() round-trip decompilation for binary and unary operators.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


PASS decompiledFunction is 'function () { x + + y;}'
PASS decompiledFunction is 'function () { x + - y;}'
PASS decompiledFunction is 'function () { x - + y;}'
PASS decompiledFunction is 'function () { x - - y;}'
PASS decompiledFunction is 'function () { x * + y;}'
PASS decompiledFunction is 'function () { x * - y;}'
PASS decompiledFunction is 'function () { x / + y;}'
PASS decompiledFunction is 'function () { x / - y;}'
PASS decompiledFunction is 'function () { x % + y;}'
PASS decompiledFunction is 'function () { x % - y;}'
PASS decompiledFunction is 'function () { x++ + y;}'
PASS decompiledFunction is 'function () { x++ - y;}'
PASS decompiledFunction is 'function () { x++ * y;}'
PASS decompiledFunction is 'function () { x++ / y;}'
PASS decompiledFunction is 'function () { x-- + y;}'
PASS decompiledFunction is 'function () { x-- - y;}'
PASS decompiledFunction is 'function () { x-- * y;}'
PASS decompiledFunction is 'function () { x-- / y;}'
PASS decompiledFunction is 'function () { x + ++y;}'
PASS decompiledFunction is 'function () { x - ++y;}'
PASS decompiledFunction is 'function () { x * ++y;}'
PASS decompiledFunction is 'function () { x / ++y;}'
PASS decompiledFunction is 'function () { x + --y;}'
PASS decompiledFunction is 'function () { x - --y;}'
PASS decompiledFunction is 'function () { x * --y;}'
PASS decompiledFunction is 'function () { x / --y;}'
PASS decompiledFunction is 'function () { x++ + ++y;}'
PASS decompiledFunction is 'function () { x++ - ++y;}'
PASS decompiledFunction is 'function () { x++ * ++y;}'
PASS decompiledFunction is 'function () { x++ / ++y;}'
PASS decompiledFunction is 'function () { x-- + ++y;}'
PASS decompiledFunction is 'function () { x-- - ++y;}'
PASS decompiledFunction is 'function () { x-- * ++y;}'
PASS decompiledFunction is 'function () { x-- / ++y;}'
PASS decompiledFunction is 'function () { x++ + --y;}'
PASS decompiledFunction is 'function () { x++ - --y;}'
PASS decompiledFunction is 'function () { x++ * --y;}'
PASS decompiledFunction is 'function () { x++ / --y;}'
PASS decompiledFunction is 'function () { x-- + --y;}'
PASS decompiledFunction is 'function () { x-- - --y;}'
PASS decompiledFunction is 'function () { x-- * --y;}'
PASS decompiledFunction is 'function () { x-- / --y;}'
PASS decompiledFunction is 'function () { + + x;}'
PASS decompiledFunction is 'function () { + - x;}'
PASS decompiledFunction is 'function () { - + x;}'
PASS decompiledFunction is 'function () { - - x;}'
PASS decompiledFunction is 'function () { 1;}'
PASS decompiledFunction is 'function () { -1;}'
PASS decompiledFunction is 'function () { - -1;}'
PASS decompiledFunction is 'function () { - - 0;}'
PASS decompiledFunction is 'function () { - - NaN;}'
PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,83 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. 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.
//
// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.

description("This test checks toString() round-trip decompilation for binary and unary operators.");

var tests = [
"x + + y",
"x + - y",
"x - + y",
"x - - y",
"x * + y",
"x * - y",
"x / + y",
"x / - y",
"x % + y",
"x % - y",
"x++ + y",
"x++ - y",
"x++ * y",
"x++ / y",
"x-- + y",
"x-- - y",
"x-- * y",
"x-- / y",
"x + ++y",
"x - ++y",
"x * ++y",
"x / ++y",
"x + --y",
"x - --y",
"x * --y",
"x / --y",
"x++ + ++y",
"x++ - ++y",
"x++ * ++y",
"x++ / ++y",
"x-- + ++y",
"x-- - ++y",
"x-- * ++y",
"x-- / ++y",
"x++ + --y",
"x++ - --y",
"x++ * --y",
"x++ / --y",
"x-- + --y",
"x-- - --y",
"x-- * --y",
"x-- / --y",
"+ + x",
"+ - x",
"- + x",
"- - x",
"1",
"-1",
"- -1",
"- - 0",
"- - NaN"
];

for (test in tests) {
var decompiledFunction = eval("(function () { " + tests[test] + ";})").toString().replace(/\n/g, "");
shouldBe("decompiledFunction", "'function () { " + tests[test] + ";}'");
}
@@ -0,0 +1,114 @@
# Copyright 2013 the V8 project authors. All rights reserved.
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. 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.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.

KDE JS Test

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


PASS Array().length is 0
PASS (new Array()).length is 0
PASS (new Array(3)).length is 3
PASS (new Array(11, 22)).length is 2
PASS (new Array(11, 22))[0] is 11
PASS Array(11, 22)[1] is 22
PASS (new Array(11, 22))[3] is undefined.
PASS String(new Array(11, 22)) is '11,22'
PASS var a = []; a[0] = 33; a[0] is 33
PASS var a = []; a[0] = 33; a.length is 1
PASS var a = [11, 22]; a.length = 1; String(a); is '11'
PASS var a = [11, 22]; a.length = 1; a.length; is 1
PASS caught; is true
PASS ename is 'RangeError'
PASS caught; is true
PASS ename is 'RangeError'
PASS var a = [11, 22]; a.length = 1; a[1]; is undefined.
PASS Array().toString() is ''
PASS Array(3).toString() is ',,'
PASS Array(11, 22).toString() is '11,22'
PASS String(Array(11, 22).concat(33)) is '11,22,33'
PASS String(Array(2).concat(33, 44)) is ',,33,44'
PASS String(Array(2).concat(Array(2))) is ',,,'
PASS String(Array(11,22).concat(Array(33,44))) is '11,22,33,44'
PASS String(Array(1,2).concat(3,Array(4,5))) is '1,2,3,4,5'
PASS var a = new Array(1,2,3); delete a[1]; String(a.concat(4)) is '1,,3,4'
PASS [1,2,3,4].slice(1, 3).toString() is '2,3'
PASS [1,2,3,4].slice(-3, -1).toString() is '2,3'
PASS [1,2].slice(-9, 0).length is 0
PASS [1,2].slice(1).toString() is '2'
PASS [1,2].slice().toString() is '1,2'
PASS (new Array('a')).length is 1
PASS (new Array('a'))[0] is 'a'
PASS (new Array('a'))[1] is undefined.
PASS Array('a').length is 1
PASS Array('a')[0] is 'a'
PASS String(Array()) is ''
PASS String(Array('a','b')) is 'a,b'
PASS [].length is 0
PASS ['a'].length is 1
PASS ['a'][0] is 'a'
PASS ['a',,'c'][2] is 'c'
PASS ['a',undefined,'c'][1] is undefined
PASS ['a',,'c'][1] is undefined
PASS 1 in ['a',,'c'] is false
PASS 1 in ['a',undefined,'c'] is true
PASS 1 in arrayWithDeletion is false
PASS forInSum([]) is ''
PASS forInSum(Array()) is ''
PASS forInSum(Array('a')) is 'a'
PASS forInSum([,undefined,'x','aa']) is 'undefinedxaa'
PASS forInSum(a0) is ''
PASS forInSum(a1) is 'a'
PASS String([].sort()) is ''
PASS String([3,1,'2'].sort()) is '1,2,3'
PASS String([,'x','aa'].sort()) is 'aa,x,'
PASS String([,undefined,'x','aa'].sort()) is 'aa,x,,'
PASS 2 in [,undefined,'x','aa'].sort() is true
PASS 3 in [,undefined,'x','aa'].sort() is false
PASS var a = ['aa', 'b', 'cccc', 'ddd']; String(a.sort(comp)) is 'b,aa,ddd,cccc'
PASS [0, Infinity].sort(function(a, b) { return a - b }).toString() is '0,Infinity'
PASS [].unshift('a') is 1
PASS ['c'].unshift('a', 'b') is 3
PASS var a = []; a.unshift('a'); String(a) is 'a'
PASS var a = ['c']; a.unshift('a', 'b'); String(a) is 'a,b,c'
PASS String(['a', 'b', 'c'].splice(1, 2, 'x', 'y')) is 'b,c'
PASS arr.length is 40
PASS arr[maxint] is "test"
PASS arr.length is 40
PASS arr[maxint] is undefined
PASS arr.length is maxint
PASS arr[maxint-1] is "test2"
PASS arr.length is 40
PASS arr[55.5] is "test"
PASS arr[65.11111111111111111111111111111] is "test"
PASS arr.length is 40
PASS arr[55.5] is undefined
PASS arr[65.11111111111111111111111111111] is undefined
PASS propnames.length is 3
PASS propnames[0] is '0'
PASS propnames[1] is '1'
PASS propnames[2] is '2'
PASS successfullyParsed is true

TEST COMPLETE