00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdlib.h>
00029
00030 #include "v8.h"
00031
00032 #include "accessors.h"
00033 #include "api.h"
00034 #include "arguments.h"
00035 #include "compiler.h"
00036 #include "cpu.h"
00037 #include "dateparser.h"
00038 #include "debug.h"
00039 #include "execution.h"
00040 #include "jsregexp.h"
00041 #include "platform.h"
00042 #include "runtime.h"
00043 #include "scopeinfo.h"
00044 #include "v8threads.h"
00045 #include "smart-pointer.h"
00046
00047 namespace v8 { namespace internal {
00048
00049
00050 #define RUNTIME_ASSERT(value) do { \
00051 if (!(value)) return IllegalOperation(); \
00052 } while (false)
00053
00054
00055
00056
00057 #define CONVERT_CHECKED(Type, name, obj) \
00058 RUNTIME_ASSERT(obj->Is##Type()); \
00059 Type* name = Type::cast(obj);
00060
00061 #define CONVERT_ARG_CHECKED(Type, name, index) \
00062 RUNTIME_ASSERT(args[index]->Is##Type()); \
00063 Handle<Type> name = args.at<Type>(index);
00064
00065
00066
00067
00068 #define CONVERT_BOOLEAN_CHECKED(name, obj) \
00069 RUNTIME_ASSERT(obj->IsBoolean()); \
00070 bool name = (obj)->IsTrue();
00071
00072
00073
00074
00075 #define CONVERT_DOUBLE_CHECKED(name, obj) \
00076 RUNTIME_ASSERT(obj->IsNumber()); \
00077 double name = (obj)->Number();
00078
00079
00080
00081
00082 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
00083 RUNTIME_ASSERT(obj->IsNumber()); \
00084 type name = NumberTo##Type(obj);
00085
00086
00087 static StaticResource<StringInputBuffer> string_input_buffer;
00088
00089
00090 static Object* IllegalOperation() {
00091 return Top::Throw(Heap::illegal_access_symbol());
00092 }
00093
00094
00095 static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) {
00096 CONVERT_CHECKED(JSObject, boilerplate, args[0]);
00097 return Heap::CopyJSObject(boilerplate);
00098 }
00099
00100
00101 static Handle<Map> ComputeObjectLiteralMap(
00102 Handle<Context> context,
00103 Handle<FixedArray> constant_properties,
00104 bool* is_result_from_cache) {
00105 if (FLAG_canonicalize_object_literal_maps) {
00106
00107 int number_of_properties = constant_properties->length()/2;
00108 int number_of_symbol_keys = 0;
00109 while ((number_of_symbol_keys < number_of_properties) &&
00110 (constant_properties->get(number_of_symbol_keys*2)->IsSymbol())) {
00111 number_of_symbol_keys++;
00112 }
00113
00114
00115 const int kMaxKeys = 10;
00116 if ((number_of_symbol_keys == number_of_properties) &&
00117 (number_of_symbol_keys < kMaxKeys)) {
00118
00119 Handle<FixedArray> keys = Factory::NewFixedArray(number_of_symbol_keys);
00120 for (int i = 0; i < number_of_symbol_keys; i++) {
00121 keys->set(i, constant_properties->get(i*2));
00122 }
00123 *is_result_from_cache = true;
00124 return Factory::ObjectLiteralMapFromCache(context, keys);
00125 }
00126 }
00127 *is_result_from_cache = false;
00128 return Handle<Map>(context->object_function()->initial_map());
00129 }
00130
00131
00132 static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
00133 HandleScope scope;
00134 ASSERT(args.length() == 3);
00135
00136 Handle<FixedArray> literals = args.at<FixedArray>(0);
00137 int literals_index = Smi::cast(args[1])->value();
00138 Handle<FixedArray> constant_properties = args.at<FixedArray>(2);
00139
00140
00141
00142
00143
00144
00145
00146 Handle<Context> context =
00147 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
00148
00149 bool is_result_from_cache;
00150 Handle<Map> map = ComputeObjectLiteralMap(context,
00151 constant_properties,
00152 &is_result_from_cache);
00153
00154 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
00155 {
00156 int length = constant_properties->length();
00157 OptimizedObjectForAddingMultipleProperties opt(boilerplate,
00158 !is_result_from_cache);
00159 for (int index = 0; index < length; index +=2) {
00160 Handle<Object> key(constant_properties->get(index+0));
00161 Handle<Object> value(constant_properties->get(index+1));
00162 uint32_t element_index = 0;
00163 if (key->IsSymbol()) {
00164
00165 Handle<String> name(String::cast(*key));
00166 ASSERT(!name->AsArrayIndex(&element_index));
00167 SetProperty(boilerplate, name, value, NONE);
00168 } else if (Array::IndexFromObject(*key, &element_index)) {
00169
00170 SetElement(boilerplate, element_index, value);
00171 } else {
00172
00173 ASSERT(key->IsNumber());
00174 double num = key->Number();
00175 char arr[100];
00176 Vector<char> buffer(arr, ARRAY_SIZE(arr));
00177 const char* str = DoubleToCString(num, buffer);
00178 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
00179 SetProperty(boilerplate, name, value, NONE);
00180 }
00181 }
00182 }
00183
00184
00185 literals->set(literals_index, *boilerplate);
00186
00187 return *boilerplate;
00188 }
00189
00190
00191 static Object* Runtime_CreateArrayLiteral(Arguments args) {
00192
00193
00194
00195
00196
00197 ASSERT(args.length() == 2);
00198 CONVERT_CHECKED(FixedArray, elements, args[0]);
00199 CONVERT_CHECKED(FixedArray, literals, args[1]);
00200 JSFunction* constructor =
00201 JSFunction::GlobalContextFromLiterals(literals)->array_function();
00202
00203 Object* object = Heap::AllocateJSObject(constructor);
00204 if (object->IsFailure()) return object;
00205
00206
00207 Object* content = elements->Copy();
00208 if (content->IsFailure()) return content;
00209
00210
00211 JSArray::cast(object)->SetContent(FixedArray::cast(content));
00212 return object;
00213 }
00214
00215
00216 static Object* Runtime_ClassOf(Arguments args) {
00217 NoHandleAllocation ha;
00218 ASSERT(args.length() == 1);
00219 Object* obj = args[0];
00220 if (!obj->IsJSObject()) return Heap::null_value();
00221 return JSObject::cast(obj)->class_name();
00222 }
00223
00224
00225 static Object* Runtime_HasStringClass(Arguments args) {
00226 return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::String_symbol()));
00227 }
00228
00229
00230 static Object* Runtime_HasDateClass(Arguments args) {
00231 return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Date_symbol()));
00232 }
00233
00234
00235 static Object* Runtime_HasArrayClass(Arguments args) {
00236 return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Array_symbol()));
00237 }
00238
00239
00240 static Object* Runtime_HasFunctionClass(Arguments args) {
00241 return Heap::ToBoolean(
00242 args[0]->HasSpecificClassOf(Heap::function_class_symbol()));
00243 }
00244
00245
00246 static Object* Runtime_HasNumberClass(Arguments args) {
00247 return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Number_symbol()));
00248 }
00249
00250
00251 static Object* Runtime_HasBooleanClass(Arguments args) {
00252 return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Boolean_symbol()));
00253 }
00254
00255
00256 static Object* Runtime_HasArgumentsClass(Arguments args) {
00257 return Heap::ToBoolean(
00258 args[0]->HasSpecificClassOf(Heap::Arguments_symbol()));
00259 }
00260
00261
00262 static Object* Runtime_HasRegExpClass(Arguments args) {
00263 return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::RegExp_symbol()));
00264 }
00265
00266
00267 static Object* Runtime_IsInPrototypeChain(Arguments args) {
00268 NoHandleAllocation ha;
00269 ASSERT(args.length() == 2);
00270
00271 Object* O = args[0];
00272 Object* V = args[1];
00273 while (true) {
00274 Object* prototype = V->GetPrototype();
00275 if (prototype->IsNull()) return Heap::false_value();
00276 if (O == prototype) return Heap::true_value();
00277 V = prototype;
00278 }
00279 }
00280
00281
00282 static Object* Runtime_IsConstructCall(Arguments args) {
00283 NoHandleAllocation ha;
00284 ASSERT(args.length() == 0);
00285 JavaScriptFrameIterator it;
00286 return Heap::ToBoolean(it.frame()->IsConstructor());
00287 }
00288
00289
00290 static Object* Runtime_RegExpCompile(Arguments args) {
00291 HandleScope scope;
00292 ASSERT(args.length() == 3);
00293 CONVERT_CHECKED(JSRegExp, raw_re, args[0]);
00294 Handle<JSRegExp> re(raw_re);
00295 CONVERT_CHECKED(String, raw_pattern, args[1]);
00296 Handle<String> pattern(raw_pattern);
00297 CONVERT_CHECKED(String, raw_flags, args[2]);
00298 Handle<String> flags(raw_flags);
00299 return *RegExpImpl::Compile(re, pattern, flags);
00300 }
00301
00302
00303 static Object* Runtime_CreateApiFunction(Arguments args) {
00304 HandleScope scope;
00305 ASSERT(args.length() == 1);
00306 CONVERT_CHECKED(FunctionTemplateInfo, raw_data, args[0]);
00307 Handle<FunctionTemplateInfo> data(raw_data);
00308 return *Factory::CreateApiFunction(data);
00309 }
00310
00311
00312 static Object* Runtime_IsTemplate(Arguments args) {
00313 ASSERT(args.length() == 1);
00314 Object* arg = args[0];
00315 bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
00316 return Heap::ToBoolean(result);
00317 }
00318
00319
00320 static Object* Runtime_GetTemplateField(Arguments args) {
00321 ASSERT(args.length() == 2);
00322 CONVERT_CHECKED(HeapObject, templ, args[0]);
00323 CONVERT_CHECKED(Smi, field, args[1]);
00324 int index = field->value();
00325 int offset = index * kPointerSize + HeapObject::kHeaderSize;
00326 InstanceType type = templ->map()->instance_type();
00327 RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
00328 type == OBJECT_TEMPLATE_INFO_TYPE);
00329 RUNTIME_ASSERT(offset > 0);
00330 if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
00331 RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
00332 } else {
00333 RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
00334 }
00335 return *HeapObject::RawField(templ, offset);
00336 }
00337
00338
00339 static Object* ThrowRedeclarationError(const char* type, Handle<String> name) {
00340 HandleScope scope;
00341 Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type));
00342 Handle<Object> args[2] = { type_handle, name };
00343 Handle<Object> error =
00344 Factory::NewTypeError("redeclaration", HandleVector(args, 2));
00345 return Top::Throw(*error);
00346 }
00347
00348
00349 static Object* Runtime_DeclareGlobals(Arguments args) {
00350 HandleScope scope;
00351 Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());
00352
00353 CONVERT_ARG_CHECKED(FixedArray, pairs, 0);
00354 Handle<Context> context = args.at<Context>(1);
00355 bool is_eval = Smi::cast(args[2])->value() == 1;
00356
00357
00358
00359
00360
00361 PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
00362
00363
00364 OptimizedObjectForAddingMultipleProperties ba(global, pairs->length()/2 > 5);
00365
00366
00367 int length = pairs->length();
00368 for (int i = 0; i < length; i += 2) {
00369 HandleScope scope;
00370 Handle<String> name(String::cast(pairs->get(i)));
00371 Handle<Object> value(pairs->get(i + 1));
00372
00373
00374
00375
00376 bool is_const_property = value->IsTheHole();
00377
00378 if (value->IsUndefined() || is_const_property) {
00379
00380
00381 LookupResult lookup;
00382 global->Lookup(*name, &lookup);
00383 if (lookup.IsProperty()) {
00384
00385
00386
00387
00388 bool is_local = (*global == lookup.holder());
00389
00390
00391 PropertyAttributes attributes = global->GetPropertyAttribute(*name);
00392 bool is_read_only = (attributes & READ_ONLY) != 0;
00393 if (lookup.type() == INTERCEPTOR) {
00394
00395
00396
00397 if (attributes != ABSENT) {
00398
00399 if (is_local && (is_read_only || is_const_property)) {
00400 const char* type = (is_read_only) ? "const" : "var";
00401 return ThrowRedeclarationError(type, name);
00402 };
00403
00404
00405 continue;
00406 }
00407
00408
00409 } else {
00410 if (is_local && (is_read_only || is_const_property)) {
00411 const char* type = (is_read_only) ? "const" : "var";
00412 return ThrowRedeclarationError(type, name);
00413 }
00414
00415
00416 continue;
00417 }
00418 }
00419 } else {
00420
00421 Handle<JSFunction> boilerplate = Handle<JSFunction>::cast(value);
00422 Handle<JSFunction> function =
00423 Factory::NewFunctionFromBoilerplate(boilerplate, context);
00424 value = function;
00425 }
00426
00427 LookupResult lookup;
00428 global->LocalLookup(*name, &lookup);
00429
00430 PropertyAttributes attributes = is_const_property
00431 ? static_cast<PropertyAttributes>(base | READ_ONLY)
00432 : base;
00433
00434 if (lookup.IsProperty()) {
00435
00436
00437
00438
00439
00440
00441
00442 if (lookup.type() != INTERCEPTOR &&
00443 (lookup.IsReadOnly() || is_const_property)) {
00444 const char* type = (lookup.IsReadOnly()) ? "const" : "var";
00445 return ThrowRedeclarationError(type, name);
00446 }
00447 SetProperty(global, name, value, attributes);
00448 } else {
00449
00450
00451
00452
00453
00454
00455 IgnoreAttributesAndSetLocalProperty(global, name, value, attributes);
00456 }
00457 }
00458
00459 return Heap::undefined_value();
00460 }
00461
00462
00463 static Object* Runtime_DeclareContextSlot(Arguments args) {
00464 HandleScope scope;
00465 ASSERT(args.length() == 4);
00466
00467 CONVERT_ARG_CHECKED(Context, context, 0);
00468 Handle<String> name(String::cast(args[1]));
00469 PropertyAttributes mode =
00470 static_cast<PropertyAttributes>(Smi::cast(args[2])->value());
00471 ASSERT(mode == READ_ONLY || mode == NONE);
00472 Handle<Object> initial_value(args[3]);
00473
00474
00475 context = Handle<Context>(context->fcontext());
00476
00477 int index;
00478 PropertyAttributes attributes;
00479 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
00480 Handle<Object> holder =
00481 context->Lookup(name, flags, &index, &attributes);
00482
00483 if (attributes != ABSENT) {
00484
00485
00486
00487 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
00488
00489 ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
00490 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
00491 return ThrowRedeclarationError(type, name);
00492 }
00493
00494
00495 if (*initial_value != NULL) {
00496 if (index >= 0) {
00497
00498
00499
00500 ASSERT(holder.is_identical_to(context));
00501 if (((attributes & READ_ONLY) == 0) ||
00502 context->get(index)->IsTheHole()) {
00503 context->set(index, *initial_value);
00504 }
00505 } else {
00506
00507 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
00508 SetProperty(context_ext, name, initial_value, mode);
00509 }
00510 }
00511
00512 } else {
00513
00514
00515
00516 Handle<JSObject> context_ext;
00517 if (context->has_extension()) {
00518
00519 context_ext = Handle<JSObject>(context->extension());
00520 } else {
00521
00522
00523 context_ext = Factory::NewJSObject(Top::context_extension_function());
00524
00525 context->set_extension(*context_ext);
00526 }
00527 ASSERT(*context_ext != NULL);
00528
00529
00530
00531
00532 ASSERT(!context_ext->HasLocalProperty(*name));
00533 Handle<Object> value(Heap::undefined_value());
00534 if (*initial_value != NULL) value = initial_value;
00535 SetProperty(context_ext, name, value, mode);
00536 ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode);
00537 }
00538
00539 return Heap::undefined_value();
00540 }
00541
00542
00543 static Object* Runtime_InitializeVarGlobal(Arguments args) {
00544 NoHandleAllocation nha;
00545
00546
00547
00548 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
00549 bool assign = args.length() == 2;
00550
00551 CONVERT_ARG_CHECKED(String, name, 0);
00552 GlobalObject* global = Top::context()->global();
00553
00554
00555
00556 PropertyAttributes attributes = DONT_DELETE;
00557
00558
00559
00560
00561
00562
00563 LookupResult lookup;
00564 global->LocalLookup(*name, &lookup);
00565 if (!lookup.IsProperty()) {
00566 Object* value = (assign) ? args[1] : Heap::undefined_value();
00567 return global->IgnoreAttributesAndSetLocalProperty(*name,
00568 value,
00569 attributes);
00570 }
00571
00572
00573 if (lookup.IsReadOnly()) {
00574 return ThrowRedeclarationError("const", name);
00575 }
00576
00577
00578
00579 bool found = true;
00580 PropertyType type = lookup.type();
00581 if (type == INTERCEPTOR) {
00582 PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
00583 if (intercepted == ABSENT) {
00584
00585
00586 found = false;
00587 } else if ((intercepted & READ_ONLY) != 0) {
00588
00589
00590
00591 return ThrowRedeclarationError("const", name);
00592 }
00593
00594 global = Top::context()->global();
00595 }
00596
00597 if (found && !assign) {
00598
00599
00600 return Heap::undefined_value();
00601 }
00602
00603
00604 Object* value = (assign) ? args[1] : Heap::undefined_value();
00605 return global->SetProperty(&lookup, *name, value, attributes);
00606 }
00607
00608
00609 static Object* Runtime_InitializeConstGlobal(Arguments args) {
00610
00611
00612
00613 RUNTIME_ASSERT(args.length() == 2);
00614 CONVERT_ARG_CHECKED(String, name, 0);
00615 Handle<Object> value = args.at<Object>(1);
00616
00617
00618 GlobalObject* global = Top::context()->global();
00619
00620
00621
00622 PropertyAttributes attributes =
00623 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
00624
00625
00626
00627
00628
00629
00630 LookupResult lookup;
00631 global->LocalLookup(*name, &lookup);
00632 if (!lookup.IsProperty()) {
00633 return global->IgnoreAttributesAndSetLocalProperty(*name,
00634 *value,
00635 attributes);
00636 }
00637
00638
00639
00640
00641 if (!lookup.IsReadOnly()) {
00642 if (lookup.type() != INTERCEPTOR) {
00643 return ThrowRedeclarationError("var", name);
00644 }
00645
00646 PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
00647
00648
00649
00650 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
00651 return ThrowRedeclarationError("var", name);
00652 }
00653
00654
00655
00656
00657 global = Top::context()->global();
00658
00659
00660
00661
00662 global->SetProperty(*name, *value, attributes);
00663 return *value;
00664 }
00665
00666
00667
00668
00669 PropertyType type = lookup.type();
00670 if (type == FIELD) {
00671 FixedArray* properties = global->properties();
00672 int index = lookup.GetFieldIndex();
00673 if (properties->get(index)->IsTheHole()) {
00674 properties->set(index, *value);
00675 }
00676 } else if (type == NORMAL) {
00677 Dictionary* dictionary = global->property_dictionary();
00678 int entry = lookup.GetDictionaryEntry();
00679 if (dictionary->ValueAt(entry)->IsTheHole()) {
00680 dictionary->ValueAtPut(entry, *value);
00681 }
00682 } else {
00683
00684
00685 ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
00686 }
00687
00688
00689 return *value;
00690 }
00691
00692
00693 static Object* Runtime_InitializeConstContextSlot(Arguments args) {
00694 HandleScope scope;
00695 ASSERT(args.length() == 3);
00696
00697 Handle<Object> value(args[0]);
00698 ASSERT(!value->IsTheHole());
00699 CONVERT_ARG_CHECKED(Context, context, 1);
00700 Handle<String> name(String::cast(args[2]));
00701
00702
00703 context = Handle<Context>(context->fcontext());
00704
00705 int index;
00706 PropertyAttributes attributes;
00707 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
00708 Handle<Object> holder =
00709 context->Lookup(name, flags, &index, &attributes);
00710
00711
00712
00713 ASSERT(attributes != ABSENT && (attributes & READ_ONLY) != 0);
00714
00715
00716
00717 if (index >= 0) {
00718
00719
00720 ASSERT(holder.is_identical_to(context));
00721 if (context->get(index)->IsTheHole()) {
00722 context->set(index, *value);
00723 }
00724 return *value;
00725 }
00726
00727
00728 Handle<JSObject> context_ext(JSObject::cast(*holder));
00729
00730
00731
00732
00733
00734 LookupResult lookup;
00735 context_ext->LocalLookupRealNamedProperty(*name, &lookup);
00736 ASSERT(lookup.IsProperty());
00737 ASSERT(lookup.IsReadOnly());
00738
00739 PropertyType type = lookup.type();
00740 if (type == FIELD) {
00741 FixedArray* properties = context_ext->properties();
00742 int index = lookup.GetFieldIndex();
00743 if (properties->get(index)->IsTheHole()) {
00744 properties->set(index, *value);
00745 }
00746 } else if (type == NORMAL) {
00747 Dictionary* dictionary = context_ext->property_dictionary();
00748 int entry = lookup.GetDictionaryEntry();
00749 if (dictionary->ValueAt(entry)->IsTheHole()) {
00750 dictionary->ValueAtPut(entry, *value);
00751 }
00752 } else {
00753
00754
00755 UNREACHABLE();
00756 }
00757 return *value;
00758 }
00759
00760
00761 static Object* Runtime_RegExpExec(Arguments args) {
00762 HandleScope scope;
00763 ASSERT(args.length() == 3);
00764 CONVERT_CHECKED(JSRegExp, raw_regexp, args[0]);
00765 Handle<JSRegExp> regexp(raw_regexp);
00766 CONVERT_CHECKED(String, raw_subject, args[1]);
00767 Handle<String> subject(raw_subject);
00768 Handle<Object> index(args[2]);
00769 ASSERT(index->IsNumber());
00770 return *RegExpImpl::Exec(regexp, subject, index);
00771 }
00772
00773
00774 static Object* Runtime_RegExpExecGlobal(Arguments args) {
00775 HandleScope scope;
00776 ASSERT(args.length() == 2);
00777 CONVERT_CHECKED(JSRegExp, raw_regexp, args[0]);
00778 Handle<JSRegExp> regexp(raw_regexp);
00779 CONVERT_CHECKED(String, raw_subject, args[1]);
00780 Handle<String> subject(raw_subject);
00781 return *RegExpImpl::ExecGlobal(regexp, subject);
00782 }
00783
00784
00785 static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
00786 HandleScope scope;
00787 ASSERT(args.length() == 4);
00788 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
00789 int index = Smi::cast(args[1])->value();
00790 Handle<String> pattern = args.at<String>(2);
00791 Handle<String> flags = args.at<String>(3);
00792
00793
00794
00795
00796
00797
00798 Handle<JSFunction> constructor =
00799 Handle<JSFunction>(
00800 JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
00801
00802 bool has_pending_exception;
00803 Handle<Object> regexp =
00804 RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
00805 &has_pending_exception);
00806 if (has_pending_exception) {
00807 ASSERT(Top::has_pending_exception());
00808 return Failure::Exception();
00809 }
00810 literals->set(index, *regexp);
00811 return *regexp;
00812 }
00813
00814
00815 static Object* Runtime_FunctionGetName(Arguments args) {
00816 NoHandleAllocation ha;
00817 ASSERT(args.length() == 1);
00818
00819 CONVERT_CHECKED(JSFunction, f, args[0]);
00820 return f->shared()->name();
00821 }
00822
00823
00824 static Object* Runtime_FunctionSetName(Arguments args) {
00825 NoHandleAllocation ha;
00826 ASSERT(args.length() == 2);
00827
00828 CONVERT_CHECKED(JSFunction, f, args[0]);
00829 CONVERT_CHECKED(String, name, args[1]);
00830 f->shared()->set_name(name);
00831 return Heap::undefined_value();
00832 }
00833
00834
00835 static Object* Runtime_FunctionGetScript(Arguments args) {
00836 HandleScope scope;
00837 ASSERT(args.length() == 1);
00838
00839 CONVERT_CHECKED(JSFunction, fun, args[0]);
00840 Handle<Object> script = Handle<Object>(fun->shared()->script());
00841 if (!script->IsScript()) return Heap::undefined_value();
00842
00843 return *GetScriptWrapper(Handle<Script>::cast(script));
00844 }
00845
00846
00847 static Object* Runtime_FunctionGetSourceCode(Arguments args) {
00848 NoHandleAllocation ha;
00849 ASSERT(args.length() == 1);
00850
00851 CONVERT_CHECKED(JSFunction, f, args[0]);
00852 return f->shared()->GetSourceCode();
00853 }
00854
00855
00856 static Object* Runtime_FunctionGetScriptSourcePosition(Arguments args) {
00857 NoHandleAllocation ha;
00858 ASSERT(args.length() == 1);
00859
00860 CONVERT_CHECKED(JSFunction, fun, args[0]);
00861 int pos = fun->shared()->start_position();
00862 return Smi::FromInt(pos);
00863 }
00864
00865
00866 static Object* Runtime_FunctionSetInstanceClassName(Arguments args) {
00867 NoHandleAllocation ha;
00868 ASSERT(args.length() == 2);
00869
00870 CONVERT_CHECKED(JSFunction, fun, args[0]);
00871 CONVERT_CHECKED(String, name, args[1]);
00872 fun->SetInstanceClassName(name);
00873 return Heap::undefined_value();
00874 }
00875
00876
00877 static Object* Runtime_FunctionSetLength(Arguments args) {
00878 NoHandleAllocation ha;
00879 ASSERT(args.length() == 2);
00880
00881 CONVERT_CHECKED(JSFunction, fun, args[0]);
00882 CONVERT_CHECKED(Smi, length, args[1]);
00883 fun->shared()->set_length(length->value());
00884 return length;
00885 }
00886
00887
00888 static Object* Runtime_FunctionSetPrototype(Arguments args) {
00889 NoHandleAllocation ha;
00890 ASSERT(args.length() == 2);
00891
00892 CONVERT_CHECKED(JSFunction, fun, args[0]);
00893 Object* obj = Accessors::FunctionSetPrototype(fun, args[1], NULL);
00894 if (obj->IsFailure()) return obj;
00895 return args[0];
00896 }
00897
00898
00899 static Object* Runtime_SetCode(Arguments args) {
00900 HandleScope scope;
00901 ASSERT(args.length() == 2);
00902
00903 CONVERT_CHECKED(JSFunction, raw_target, args[0]);
00904 Handle<JSFunction> target(raw_target);
00905 Handle<Object> code = args.at<Object>(1);
00906
00907 Handle<Context> context(target->context());
00908
00909 if (!code->IsNull()) {
00910 RUNTIME_ASSERT(code->IsJSFunction());
00911 Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
00912 SetExpectedNofProperties(target, fun->shared()->expected_nof_properties());
00913 if (!fun->is_compiled() && !CompileLazy(fun, KEEP_EXCEPTION)) {
00914 return Failure::Exception();
00915 }
00916
00917
00918 target->set_code(fun->code());
00919 target->shared()->set_length(fun->shared()->length());
00920 target->shared()->set_formal_parameter_count(
00921 fun->shared()->formal_parameter_count());
00922
00923
00924
00925
00926 target->shared()->set_script(Heap::undefined_value());
00927 context = Handle<Context>(fun->context());
00928
00929
00930
00931 int number_of_literals = fun->NumberOfLiterals();
00932 Handle<FixedArray> literals =
00933 Factory::NewFixedArray(number_of_literals, TENURED);
00934 if (number_of_literals > 0) {
00935
00936
00937
00938 literals->set(JSFunction::kLiteralGlobalContextIndex,
00939 context->global_context());
00940 }
00941 target->set_literals(*literals, SKIP_WRITE_BARRIER);
00942 }
00943
00944 target->set_context(*context);
00945 return *target;
00946 }
00947
00948
00949 static Object* CharCodeAt(String* subject, Object* index) {
00950 uint32_t i = 0;
00951 if (!Array::IndexFromObject(index, &i)) return Heap::nan_value();
00952
00953
00954
00955 subject->TryFlatten();
00956 if (i >= static_cast<uint32_t>(subject->length())) return Heap::nan_value();
00957 return Smi::FromInt(subject->Get(i));
00958 }
00959
00960
00961 static Object* Runtime_StringCharCodeAt(Arguments args) {
00962 NoHandleAllocation ha;
00963 ASSERT(args.length() == 2);
00964
00965 CONVERT_CHECKED(String, subject, args[0]);
00966 Object* index = args[1];
00967 return CharCodeAt(subject, index);
00968 }
00969
00970
00971 static Object* Runtime_CharFromCode(Arguments args) {
00972 NoHandleAllocation ha;
00973 ASSERT(args.length() == 1);
00974 uint32_t code;
00975 if (Array::IndexFromObject(args[0], &code)) {
00976 if (code <= 0xffff) {
00977 return Heap::LookupSingleCharacterStringFromCode(code);
00978 }
00979 }
00980 return Heap::empty_string();
00981 }
00982
00983
00984
00985
00986 static const int kBMMaxShift = 0xff;
00987
00988 static const int kBMAlphabetSize = 0x100;
00989
00990
00991 static const int kBMMinPatternLength = 5;
00992
00993
00994
00995
00996 class BMGoodSuffixBuffers {
00997 public:
00998 BMGoodSuffixBuffers() {}
00999 inline void init(int needle_length) {
01000 ASSERT(needle_length > 1);
01001 int start = needle_length < kBMMaxShift ? 0 : needle_length - kBMMaxShift;
01002 int len = needle_length - start;
01003 biased_suffixes_ = suffixes_ - start;
01004 biased_good_suffix_shift_ = good_suffix_shift_ - start;
01005 for (int i = 0; i <= len; i++) {
01006 good_suffix_shift_[i] = len;
01007 }
01008 }
01009 inline int& suffix(int index) {
01010 ASSERT(biased_suffixes_ + index >= suffixes_);
01011 return biased_suffixes_[index];
01012 }
01013 inline int& shift(int index) {
01014 ASSERT(biased_good_suffix_shift_ + index >= good_suffix_shift_);
01015 return biased_good_suffix_shift_[index];
01016 }
01017 private:
01018 int suffixes_[kBMMaxShift + 1];
01019 int good_suffix_shift_[kBMMaxShift + 1];
01020 int* biased_suffixes_;
01021 int* biased_good_suffix_shift_;
01022 DISALLOW_COPY_AND_ASSIGN(BMGoodSuffixBuffers);
01023 };
01024
01025
01026 static int bad_char_occurence[kBMAlphabetSize];
01027 static BMGoodSuffixBuffers bmgs_buffers;
01028
01029
01030 template <typename pchar>
01031 static void BoyerMoorePopulateBadCharTable(Vector<const pchar> pattern,
01032 int start) {
01033
01034
01035
01036 int table_size = (sizeof(pchar) == 1) ? String::kMaxAsciiCharCode + 1
01037 : kBMAlphabetSize;
01038 if (start == 0) {
01039 memset(bad_char_occurence, -1, table_size * sizeof(*bad_char_occurence));
01040 } else {
01041 for (int i = 0; i < table_size; i++) {
01042 bad_char_occurence[i] = start - 1;
01043 }
01044 }
01045 for (int i = start; i < pattern.length() - 1; i++) {
01046 pchar c = pattern[i];
01047 int bucket = (sizeof(pchar) ==1) ? c : c % kBMAlphabetSize;
01048 bad_char_occurence[bucket] = i;
01049 }
01050 }
01051
01052 template <typename pchar>
01053 static void BoyerMoorePopulateGoodSuffixTable(Vector<const pchar> pattern,
01054 int start) {
01055 int m = pattern.length();
01056 int len = m - start;
01057
01058 bmgs_buffers.init(m);
01059
01060 bmgs_buffers.shift(m-1) = 1;
01061 bmgs_buffers.suffix(m) = m + 1;
01062 pchar last_char = pattern[m - 1];
01063 int suffix = m + 1;
01064 for (int i = m; i > start;) {
01065 for (pchar c = pattern[i - 1]; suffix <= m && c != pattern[suffix - 1];) {
01066 if (bmgs_buffers.shift(suffix) == len) {
01067 bmgs_buffers.shift(suffix) = suffix - i;
01068 }
01069 suffix = bmgs_buffers.suffix(suffix);
01070 }
01071 i--;
01072 suffix--;
01073 bmgs_buffers.suffix(i) = suffix;
01074 if (suffix == m) {
01075
01076 while (i > start && pattern[i - 1] != last_char) {
01077 if (bmgs_buffers.shift(m) == len) {
01078 bmgs_buffers.shift(m) = m - i;
01079 }
01080 i--;
01081 bmgs_buffers.suffix(i) = m;
01082 }
01083 if (i > start) {
01084 i--;
01085 suffix--;
01086 bmgs_buffers.suffix(i) = suffix;
01087 }
01088 }
01089 }
01090 if (suffix < m) {
01091 for (int i = start; i <= m; i++) {
01092 if (bmgs_buffers.shift(i) == len) {
01093 bmgs_buffers.shift(i) = suffix - start;
01094 }
01095 if (i == suffix) {
01096 suffix = bmgs_buffers.suffix(suffix);
01097 }
01098 }
01099 }
01100 }
01101
01102 template <typename schar, typename pchar>
01103 static inline int CharOccurence(int char_code) {
01104 if (sizeof(schar) == 1) {
01105 return bad_char_occurence[char_code];
01106 }
01107 if (sizeof(pchar) == 1) {
01108 if (char_code > String::kMaxAsciiCharCode) {
01109 return -1;
01110 }
01111 return bad_char_occurence[char_code];
01112 }
01113 return bad_char_occurence[char_code % kBMAlphabetSize];
01114 }
01115
01116
01117
01118
01119
01120 template <typename schar, typename pchar>
01121 static int BoyerMooreSimplified(Vector<const schar> subject,
01122 Vector<const pchar> pattern,
01123 int start_index,
01124 bool* complete) {
01125 int n = subject.length();
01126 int m = pattern.length();
01127
01128 int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
01129
01130 BoyerMoorePopulateBadCharTable(pattern, start);
01131
01132 int badness = -m;
01133 int idx;
01134 pchar last_char = pattern[m - 1];
01135
01136 for (idx = start_index; idx <= n - m;) {
01137 int j = m - 1;
01138 int c;
01139 while (last_char != (c = subject[idx + j])) {
01140 int bc_occ = CharOccurence<schar, pchar>(c);
01141 int shift = j - bc_occ;
01142 idx += shift;
01143 badness += 1 - shift;
01144 if (idx > n - m) {
01145 *complete = true;
01146 return -1;
01147 }
01148 }
01149 j--;
01150 while (j >= 0 && pattern[j] == (c = subject[idx + j])) j--;
01151 if (j < 0) {
01152 *complete = true;
01153 return idx;
01154 } else {
01155 int bc_occ = CharOccurence<schar, pchar>(c);
01156 int shift = bc_occ < j ? j - bc_occ : 1;
01157 idx += shift;
01158
01159
01160
01161
01162 badness += (m - j) - shift;
01163 if (badness > 0) {
01164 *complete = false;
01165 return idx;
01166 }
01167 }
01168 }
01169 *complete = true;
01170 return -1;
01171 }
01172
01173
01174 template <typename schar, typename pchar>
01175 static int BoyerMooreIndexOf(Vector<const schar> subject,
01176 Vector<const pchar> pattern,
01177 int idx) {
01178 int n = subject.length();
01179 int m = pattern.length();
01180
01181 int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
01182
01183
01184 BoyerMoorePopulateGoodSuffixTable(pattern, start);
01185 pchar last_char = pattern[m - 1];
01186
01187 do {
01188 int j = m - 1;
01189 schar c;
01190 while (last_char != (c = subject[idx + j])) {
01191 int shift = j - CharOccurence<schar, pchar>(c);
01192 idx += shift;
01193 if (idx > n - m) {
01194 return -1;
01195 }
01196 }
01197 while (j >= 0 && pattern[j] == (c = subject[idx + j])) j--;
01198 if (j < 0) {
01199 return idx;
01200 } else if (j < start) {
01201
01202 idx += 1;
01203 } else {
01204 int gs_shift = bmgs_buffers.shift(j + 1);
01205 int bc_occ = CharOccurence<schar, pchar>(c);
01206 int shift = j - bc_occ;
01207 shift = (gs_shift > shift) ? gs_shift : shift;
01208 idx += shift;
01209 }
01210 } while (idx <= n - m);
01211
01212 return -1;
01213 }
01214
01215
01216 template <typename schar>
01217 static int SingleCharIndexOf(Vector<const schar> string,
01218 uc16 pattern_char,
01219 int start_index) {
01220 if (sizeof(schar) == 1 && pattern_char > String::kMaxAsciiCharCode) {
01221 return -1;
01222 }
01223 for (int i = start_index, n = string.length(); i < n; i++) {
01224 if (pattern_char == string[i]) {
01225 return i;
01226 }
01227 }
01228 return -1;
01229 }
01230
01231
01232
01233
01234
01235
01236
01237 template <typename pchar, typename schar>
01238 static int SimpleIndexOf(Vector<const schar> subject,
01239 Vector<const pchar> pattern,
01240 int idx,
01241 bool* complete) {
01242
01243
01244
01245 int badness = -10 - (pattern.length() << 2);
01246
01247
01248 pchar pattern_first_char = pattern[0];
01249
01250 for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
01251 badness++;
01252 if (badness > 0) {
01253 *complete = false;
01254 return (i);
01255 }
01256 if (subject[i] != pattern_first_char) continue;
01257 int j = 1;
01258 do {
01259 if (pattern[j] != subject[i+j]) {
01260 break;
01261 }
01262 j++;
01263 } while (j < pattern.length());
01264 if (j == pattern.length()) {
01265 *complete = true;
01266 return i;
01267 }
01268 badness += j;
01269 }
01270 *complete = true;
01271 return -1;
01272 }
01273
01274
01275 template <typename pchar, typename schar>
01276 static int SimpleIndexOf(Vector<const schar> subject,
01277 Vector<const pchar> pattern,
01278 int idx) {
01279 pchar pattern_first_char = pattern[0];
01280 for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
01281 if (subject[i] != pattern_first_char) continue;
01282 int j = 1;
01283 do {
01284 if (pattern[j] != subject[i+j]) {
01285 break;
01286 }
01287 j++;
01288 } while (j < pattern.length());
01289 if (j == pattern.length()) {
01290 return i;
01291 }
01292 }
01293 return -1;
01294 }
01295
01296
01297
01298 template <typename schar, typename pchar>
01299 static int StringMatchStrategy(Vector<const schar> sub,
01300 Vector<const pchar> pat,
01301 int start_index) {
01302 ASSERT(pat.length() > 1);
01303
01304
01305
01306
01307 if (sizeof(pchar) > 1 && sizeof(schar) == 1) {
01308 for (int i = 0; i < pat.length(); i++) {
01309 uc16 c = pat[i];
01310 if (c > String::kMaxAsciiCharCode) {
01311 return -1;
01312 }
01313 }
01314 }
01315 if (pat.length() < kBMMinPatternLength) {
01316
01317
01318
01319 return SimpleIndexOf(sub, pat, start_index);
01320 }
01321
01322 bool complete;
01323 int idx = SimpleIndexOf(sub, pat, start_index, &complete);
01324 if (complete) return idx;
01325 idx = BoyerMooreSimplified(sub, pat, idx, &complete);
01326 if (complete) return idx;
01327 return BoyerMooreIndexOf(sub, pat, idx);
01328 }
01329
01330
01331
01332
01333 int Runtime::StringMatch(Handle<String> sub,
01334 Handle<String> pat,
01335 int start_index) {
01336 ASSERT(0 <= start_index);
01337 ASSERT(start_index <= sub->length());
01338
01339 int pattern_length = pat->length();
01340 if (pattern_length == 0) return start_index;
01341
01342 int subject_length = sub->length();
01343 if (start_index + pattern_length > subject_length) return -1;
01344
01345 FlattenString(sub);
01346
01347
01348
01349 if (pattern_length == 1) {
01350 AssertNoAllocation no_heap_allocation;
01351 if (sub->is_ascii_representation()) {
01352 return SingleCharIndexOf(sub->ToAsciiVector(), pat->Get(0), start_index);
01353 }
01354 return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index);
01355 }
01356
01357 FlattenString(pat);
01358
01359 AssertNoAllocation no_heap_allocation;
01360
01361 if (pat->is_ascii_representation()) {
01362 Vector<const char> pat_vector = pat->ToAsciiVector();
01363 if (sub->is_ascii_representation()) {
01364 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
01365 }
01366 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
01367 }
01368 Vector<const uc16> pat_vector = pat->ToUC16Vector();
01369 if (sub->is_ascii_representation()) {
01370 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
01371 }
01372 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
01373 }
01374
01375
01376 static Object* Runtime_StringIndexOf(Arguments args) {
01377 HandleScope scope;
01378 ASSERT(args.length() == 3);
01379
01380 CONVERT_ARG_CHECKED(String, sub, 0);
01381 CONVERT_ARG_CHECKED(String, pat, 1);
01382
01383 Object* index = args[2];
01384 uint32_t start_index;
01385 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
01386
01387 int position = Runtime::StringMatch(sub, pat, start_index);
01388 return Smi::FromInt(position);
01389 }
01390
01391
01392 static Object* Runtime_StringLastIndexOf(Arguments args) {
01393 NoHandleAllocation ha;
01394 ASSERT(args.length() == 3);
01395
01396 CONVERT_CHECKED(String, sub, args[0]);
01397 CONVERT_CHECKED(String, pat, args[1]);
01398 Object* index = args[2];
01399
01400 sub->TryFlatten();
01401 pat->TryFlatten();
01402
01403 uint32_t start_index;
01404 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
01405
01406 uint32_t pattern_length = pat->length();
01407 uint32_t sub_length = sub->length();
01408
01409 if (start_index + pattern_length > sub_length) {
01410 start_index = sub_length - pattern_length;
01411 }
01412
01413 for (int i = start_index; i >= 0; i--) {
01414 bool found = true;
01415 for (uint32_t j = 0; j < pattern_length; j++) {
01416 if (sub->Get(i + j) != pat->Get(j)) {
01417 found = false;
01418 break;
01419 }
01420 }
01421 if (found) return Smi::FromInt(i);
01422 }
01423
01424 return Smi::FromInt(-1);
01425 }
01426
01427
01428 static Object* Runtime_StringLocaleCompare(Arguments args) {
01429 NoHandleAllocation ha;
01430 ASSERT(args.length() == 2);
01431
01432 CONVERT_CHECKED(String, str1, args[0]);
01433 CONVERT_CHECKED(String, str2, args[1]);
01434
01435 if (str1 == str2) return Smi::FromInt(0);
01436 int str1_length = str1->length();
01437 int str2_length = str2->length();
01438
01439
01440 if (str1_length == 0) {
01441 if (str2_length == 0) return Smi::FromInt(0);
01442 return Smi::FromInt(-str2_length);
01443 } else {
01444 if (str2_length == 0) return Smi::FromInt(str1_length);
01445 }
01446
01447 int end = str1_length < str2_length ? str1_length : str2_length;
01448
01449
01450
01451
01452 int d = str1->Get(0) - str2->Get(0);
01453 if (d != 0) return Smi::FromInt(d);
01454
01455 str1->TryFlatten();
01456 str2->TryFlatten();
01457
01458 static StringInputBuffer buf1;
01459 static StringInputBuffer buf2;
01460
01461 buf1.Reset(str1);
01462 buf2.Reset(str2);
01463
01464 for (int i = 0; i < end; i++) {
01465 uint16_t char1 = buf1.GetNext();
01466 uint16_t char2 = buf2.GetNext();
01467 if (char1 != char2) return Smi::FromInt(char1 - char2);
01468 }
01469
01470 return Smi::FromInt(str1_length - str2_length);
01471 }
01472
01473
01474 static Object* Runtime_StringSlice(Arguments args) {
01475 NoHandleAllocation ha;
01476 ASSERT(args.length() == 3);
01477
01478 CONVERT_CHECKED(String, value, args[0]);
01479 CONVERT_DOUBLE_CHECKED(from_number, args[1]);
01480 CONVERT_DOUBLE_CHECKED(to_number, args[2]);
01481
01482 int start = FastD2I(from_number);
01483 int end = FastD2I(to_number);
01484
01485 RUNTIME_ASSERT(end >= start);
01486 RUNTIME_ASSERT(start >= 0);
01487 RUNTIME_ASSERT(end <= value->length());
01488 return value->Slice(start, end);
01489 }
01490
01491
01492 static Object* Runtime_NumberToRadixString(Arguments args) {
01493 NoHandleAllocation ha;
01494 ASSERT(args.length() == 2);
01495
01496 CONVERT_DOUBLE_CHECKED(value, args[0]);
01497 if (isnan(value)) {
01498 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
01499 }
01500 if (isinf(value)) {
01501 if (value < 0) {
01502 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
01503 }
01504 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
01505 }
01506 CONVERT_DOUBLE_CHECKED(radix_number, args[1]);
01507 int radix = FastD2I(radix_number);
01508 RUNTIME_ASSERT(2 <= radix && radix <= 36);
01509 char* str = DoubleToRadixCString(value, radix);
01510 Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
01511 DeleteArray(str);
01512 return result;
01513 }
01514
01515
01516 static Object* Runtime_NumberToFixed(Arguments args) {
01517 NoHandleAllocation ha;
01518 ASSERT(args.length() == 2);
01519
01520 CONVERT_DOUBLE_CHECKED(value, args[0]);
01521 if (isnan(value)) {
01522 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
01523 }
01524 if (isinf(value)) {
01525 if (value < 0) {
01526 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
01527 }
01528 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
01529 }
01530 CONVERT_DOUBLE_CHECKED(f_number, args[1]);
01531 int f = FastD2I(f_number);
01532 RUNTIME_ASSERT(f >= 0);
01533 char* str = DoubleToFixedCString(value, f);
01534 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
01535 DeleteArray(str);
01536 return res;
01537 }
01538
01539
01540 static Object* Runtime_NumberToExponential(Arguments args) {
01541 NoHandleAllocation ha;
01542 ASSERT(args.length() == 2);
01543
01544 CONVERT_DOUBLE_CHECKED(value, args[0]);
01545 if (isnan(value)) {
01546 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
01547 }
01548 if (isinf(value)) {
01549 if (value < 0) {
01550 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
01551 }
01552 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
01553 }
01554 CONVERT_DOUBLE_CHECKED(f_number, args[1]);
01555 int f = FastD2I(f_number);
01556 RUNTIME_ASSERT(f >= -1 && f <= 20);
01557 char* str = DoubleToExponentialCString(value, f);
01558 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
01559 DeleteArray(str);
01560 return res;
01561 }
01562
01563
01564 static Object* Runtime_NumberToPrecision(Arguments args) {
01565 NoHandleAllocation ha;
01566 ASSERT(args.length() == 2);
01567
01568 CONVERT_DOUBLE_CHECKED(value, args[0]);
01569 if (isnan(value)) {
01570 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
01571 }
01572 if (isinf(value)) {
01573 if (value < 0) {
01574 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
01575 }
01576 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
01577 }
01578 CONVERT_DOUBLE_CHECKED(f_number, args[1]);
01579 int f = FastD2I(f_number);
01580 RUNTIME_ASSERT(f >= 1 && f <= 21);
01581 char* str = DoubleToPrecisionCString(value, f);
01582 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
01583 DeleteArray(str);
01584 return res;
01585 }
01586
01587
01588
01589
01590 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
01591 if (index < static_cast<uint32_t>(string->length())) {
01592 string->TryFlatten();
01593 return LookupSingleCharacterStringFromCode(string->Get(index));
01594 }
01595 return Execution::CharAt(string, index);
01596 }
01597
01598
01599 Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) {
01600
01601 if (object->IsString()) {
01602 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
01603 if (!result->IsUndefined()) return *result;
01604 }
01605
01606
01607 if (object->IsStringObjectWithCharacterAt(index)) {
01608 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
01609 Handle<Object> result =
01610 GetCharAt(Handle<String>(String::cast(js_value->value())), index);
01611 if (!result->IsUndefined()) return *result;
01612 }
01613
01614 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
01615 Handle<Object> prototype = GetPrototype(object);
01616 return prototype->GetElement(index);
01617 }
01618
01619 return object->GetElement(index);
01620 }
01621
01622
01623 Object* Runtime::GetObjectProperty(Handle<Object> object, Handle<Object> key) {
01624 HandleScope scope;
01625
01626 if (object->IsUndefined() || object->IsNull()) {
01627 Handle<Object> args[2] = { key, object };
01628 Handle<Object> error =
01629 Factory::NewTypeError("non_object_property_load",
01630 HandleVector(args, 2));
01631 return Top::Throw(*error);
01632 }
01633
01634
01635 uint32_t index;
01636 if (Array::IndexFromObject(*key, &index)) {
01637 return GetElementOrCharAt(object, index);
01638 }
01639
01640
01641 Handle<String> name;
01642 if (key->IsString()) {
01643 name = Handle<String>::cast(key);
01644 } else {
01645 bool has_pending_exception = false;
01646 Handle<Object> converted =
01647 Execution::ToString(key, &has_pending_exception);
01648 if (has_pending_exception) return Failure::Exception();
01649 name = Handle<String>::cast(converted);
01650 }
01651
01652
01653
01654 if (name->AsArrayIndex(&index)) {
01655 return GetElementOrCharAt(object, index);
01656 } else {
01657 PropertyAttributes attr;
01658 return object->GetProperty(*name, &attr);
01659 }
01660 }
01661
01662
01663 static Object* Runtime_GetProperty(Arguments args) {
01664 NoHandleAllocation ha;
01665 ASSERT(args.length() == 2);
01666
01667 Handle<Object> object = args.at<Object>(0);
01668 Handle<Object> key = args.at<Object>(1);
01669
01670 return Runtime::GetObjectProperty(object, key);
01671 }
01672
01673
01674
01675
01676 static Object* Runtime_KeyedGetProperty(Arguments args) {
01677 NoHandleAllocation ha;
01678 ASSERT(args.length() == 2);
01679
01680
01681
01682
01683
01684
01685
01686 if (args[0]->IsJSObject() &&
01687 !args[0]->IsJSGlobalProxy() &&
01688 args[1]->IsString()) {
01689 JSObject* receiver = JSObject::cast(args[0]);
01690 String* key = String::cast(args[1]);
01691 if (receiver->HasFastProperties()) {
01692
01693 Object* obj = Heap::GetKeyedLookupCache();
01694 if (obj->IsFailure()) return obj;
01695 LookupCache* cache = LookupCache::cast(obj);
01696 Map* receiver_map = receiver->map();
01697 int offset = cache->Lookup(receiver_map, key);
01698 if (offset != LookupCache::kNotFound) {
01699 Object* value = receiver->FastPropertyAt(offset);
01700 return value->IsTheHole() ? Heap::undefined_value() : value;
01701 }
01702
01703
01704 LookupResult result;
01705 receiver->LocalLookup(key, &result);
01706 if (result.IsProperty() && result.IsLoaded() && result.type() == FIELD) {
01707 int offset = result.GetFieldIndex();
01708 Object* obj = cache->Put(receiver_map, key, offset);
01709 if (obj->IsFailure()) return obj;
01710 Heap::SetKeyedLookupCache(LookupCache::cast(obj));
01711 Object* value = receiver->FastPropertyAt(offset);
01712 return value->IsTheHole() ? Heap::undefined_value() : value;
01713 }
01714 } else {
01715
01716 Dictionary* dictionary = receiver->property_dictionary();
01717 int entry = dictionary->FindStringEntry(key);
01718 if ((entry != DescriptorArray::kNotFound) &&
01719 (dictionary->DetailsAt(entry).type() == NORMAL)) {
01720 return dictionary->ValueAt(entry);
01721 }
01722 }
01723 }
01724
01725
01726 return Runtime::GetObjectProperty(args.at<Object>(0),
01727 args.at<Object>(1));
01728 }
01729
01730
01731 Object* Runtime::SetObjectProperty(Handle<Object> object,
01732 Handle<Object> key,
01733 Handle<Object> value,
01734 PropertyAttributes attr) {
01735 HandleScope scope;
01736
01737 if (object->IsUndefined() || object->IsNull()) {
01738 Handle<Object> args[2] = { key, object };
01739 Handle<Object> error =
01740 Factory::NewTypeError("non_object_property_store",
01741 HandleVector(args, 2));
01742 return Top::Throw(*error);
01743 }
01744
01745
01746 if (!object->IsJSObject()) return *value;
01747
01748 Handle<JSObject> js_object = Handle<JSObject>::cast(object);
01749
01750
01751 uint32_t index;
01752 if (Array::IndexFromObject(*key, &index)) {
01753 ASSERT(attr == NONE);
01754
01755
01756
01757
01758
01759
01760
01761
01762 if (js_object->IsStringObjectWithCharacterAt(index)) {
01763 return *value;
01764 }
01765
01766 Handle<Object> result = SetElement(js_object, index, value);
01767 if (result.is_null()) return Failure::Exception();
01768 return *value;
01769 }
01770
01771 if (key->IsString()) {
01772 Handle<Object> result;
01773 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
01774 ASSERT(attr == NONE);
01775 result = SetElement(js_object, index, value);
01776 } else {
01777 Handle<String> key_string = Handle<String>::cast(key);
01778 key_string->TryFlatten();
01779 result = SetProperty(js_object, key_string, value, attr);
01780 }
01781 if (result.is_null()) return Failure::Exception();
01782 return *value;
01783 }
01784
01785
01786 bool has_pending_exception = false;
01787 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
01788 if (has_pending_exception) return Failure::Exception();
01789 Handle<String> name = Handle<String>::cast(converted);
01790
01791 if (name->AsArrayIndex(&index)) {
01792 ASSERT(attr == NONE);
01793 return js_object->SetElement(index, *value);
01794 } else {
01795 return js_object->SetProperty(*name, *value, attr);
01796 }
01797 }
01798
01799
01800 static Object* Runtime_SetProperty(Arguments args) {
01801 NoHandleAllocation ha;
01802 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
01803
01804 Handle<Object> object = args.at<Object>(0);
01805 Handle<Object> key = args.at<Object>(1);
01806 Handle<Object> value = args.at<Object>(2);
01807
01808
01809 PropertyAttributes attributes = NONE;
01810 if (args.length() == 4) {
01811 CONVERT_CHECKED(Smi, value_obj, args[3]);
01812 int unchecked_value = value_obj->value();
01813
01814 RUNTIME_ASSERT(
01815 (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
01816 attributes = static_cast<PropertyAttributes>(unchecked_value);
01817 }
01818 return Runtime::SetObjectProperty(object, key, value, attributes);
01819 }
01820
01821
01822
01823
01824 static Object* Runtime_IgnoreAttributesAndSetProperty(Arguments args) {
01825 NoHandleAllocation ha;
01826 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
01827 CONVERT_CHECKED(JSObject, object, args[0]);
01828 CONVERT_CHECKED(String, name, args[1]);
01829
01830 PropertyAttributes attributes = NONE;
01831 if (args.length() == 4) {
01832 CONVERT_CHECKED(Smi, value_obj, args[3]);
01833 int unchecked_value = value_obj->value();
01834
01835 RUNTIME_ASSERT(
01836 (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
01837 attributes = static_cast<PropertyAttributes>(unchecked_value);
01838 }
01839
01840 return object->
01841 IgnoreAttributesAndSetLocalProperty(name, args[2], attributes);
01842 }
01843
01844
01845 static Object* Runtime_DeleteProperty(Arguments args) {
01846 NoHandleAllocation ha;
01847 ASSERT(args.length() == 2);
01848
01849 CONVERT_CHECKED(JSObject, object, args[0]);
01850 CONVERT_CHECKED(String, key, args[1]);
01851 return object->DeleteProperty(key);
01852 }
01853
01854
01855 static Object* Runtime_HasLocalProperty(Arguments args) {
01856 NoHandleAllocation ha;
01857 ASSERT(args.length() == 2);
01858 CONVERT_CHECKED(String, key, args[1]);
01859
01860
01861 if (args[0]->IsJSObject()) {
01862 JSObject* object = JSObject::cast(args[0]);
01863 if (object->HasLocalProperty(key)) return Heap::true_value();
01864 } else if (args[0]->IsString()) {
01865
01866 uint32_t index;
01867 if (key->AsArrayIndex(&index)) {
01868 String* string = String::cast(args[0]);
01869 if (index < static_cast<uint32_t>(string->length()))
01870 return Heap::true_value();
01871 }
01872 }
01873 return Heap::false_value();
01874 }
01875
01876
01877 static Object* Runtime_HasProperty(Arguments args) {
01878 NoHandleAllocation na;
01879 ASSERT(args.length() == 2);
01880
01881
01882 if (args[0]->IsJSObject()) {
01883 JSObject* object = JSObject::cast(args[0]);
01884 CONVERT_CHECKED(String, key, args[1]);
01885 if (object->HasProperty(key)) return Heap::true_value();
01886 }
01887 return Heap::false_value();
01888 }
01889
01890
01891 static Object* Runtime_HasElement(Arguments args) {
01892 NoHandleAllocation na;
01893 ASSERT(args.length() == 2);
01894
01895
01896 if (args[0]->IsJSObject()) {
01897 JSObject* object = JSObject::cast(args[0]);
01898 CONVERT_CHECKED(Smi, index_obj, args[1]);
01899 uint32_t index = index_obj->value();
01900 if (object->HasElement(index)) return Heap::true_value();
01901 }
01902 return Heap::false_value();
01903 }
01904
01905
01906 static Object* Runtime_IsPropertyEnumerable(Arguments args) {
01907 NoHandleAllocation ha;
01908 ASSERT(args.length() == 2);
01909
01910 CONVERT_CHECKED(JSObject, object, args[0]);
01911 CONVERT_CHECKED(String, key, args[1]);
01912
01913 uint32_t index;
01914 if (key->AsArrayIndex(&index)) {
01915 return Heap::ToBoolean(object->HasElement(index));
01916 }
01917
01918 LookupResult result;
01919 object->LocalLookup(key, &result);
01920 if (!result.IsProperty()) return Heap::false_value();
01921 return Heap::ToBoolean(!result.IsDontEnum());
01922 }
01923
01924
01925 static Object* Runtime_GetPropertyNames(Arguments args) {
01926 HandleScope scope;
01927 ASSERT(args.length() == 1);
01928
01929 CONVERT_CHECKED(JSObject, raw_object, args[0]);
01930 Handle<JSObject> object(raw_object);
01931 return *GetKeysFor(object);
01932 }
01933
01934
01935
01936
01937
01938
01939
01940 static Object* Runtime_GetPropertyNamesFast(Arguments args) {
01941 ASSERT(args.length() == 1);
01942
01943 CONVERT_CHECKED(JSObject, raw_object, args[0]);
01944
01945 if (raw_object->IsSimpleEnum()) return raw_object->map();
01946
01947 HandleScope scope;
01948 Handle<JSObject> object(raw_object);
01949 Handle<FixedArray> content = GetKeysInFixedArrayFor(object);
01950
01951
01952 if (object->IsSimpleEnum()) return object->map();
01953
01954 return *content;
01955 }
01956
01957
01958 static Object* Runtime_GetArgumentsProperty(Arguments args) {
01959 NoHandleAllocation ha;
01960 ASSERT(args.length() == 1);
01961
01962
01963 JavaScriptFrameIterator it;
01964 it.AdvanceToArgumentsFrame();
01965 JavaScriptFrame* frame = it.frame();
01966
01967
01968 const uint32_t n = frame->GetProvidedParametersCount();
01969
01970
01971
01972 uint32_t index;
01973 if (Array::IndexFromObject(args[0], &index) && index < n) {
01974 return frame->GetParameter(index);
01975 }
01976
01977
01978 HandleScope scope;
01979 bool exception = false;
01980 Handle<Object> converted =
01981 Execution::ToString(args.at<Object>(0), &exception);
01982 if (exception) return Failure::Exception();
01983 Handle<String> key = Handle<String>::cast(converted);
01984
01985
01986 if (key->AsArrayIndex(&index)) {
01987 if (index < n) {
01988 return frame->GetParameter(index);
01989 } else {
01990 return Top::initial_object_prototype()->GetElement(index);
01991 }
01992 }
01993
01994
01995 if (key->Equals(Heap::length_symbol())) return Smi::FromInt(n);
01996 if (key->Equals(Heap::callee_symbol())) return frame->function();
01997
01998
01999 return Top::initial_object_prototype()->GetProperty(*key);
02000 }
02001
02002
02003 static Object* Runtime_ToBool(Arguments args) {
02004 NoHandleAllocation ha;
02005 ASSERT(args.length() == 1);
02006
02007 return args[0]->ToBoolean();
02008 }
02009
02010
02011
02012
02013 static Object* Runtime_Typeof(Arguments args) {
02014 NoHandleAllocation ha;
02015
02016 Object* obj = args[0];
02017 if (obj->IsNumber()) return Heap::number_symbol();
02018 HeapObject* heap_obj = HeapObject::cast(obj);
02019
02020
02021 if (heap_obj->map()->is_undetectable()) return Heap::undefined_symbol();
02022
02023 InstanceType instance_type = heap_obj->map()->instance_type();
02024 if (instance_type < FIRST_NONSTRING_TYPE) {
02025 return Heap::string_symbol();
02026 }
02027
02028 switch (instance_type) {
02029 case ODDBALL_TYPE:
02030 if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
02031 return Heap::boolean_symbol();
02032 }
02033 if (heap_obj->IsNull()) {
02034 return Heap::object_symbol();
02035 }
02036 ASSERT(heap_obj->IsUndefined());
02037 return Heap::undefined_symbol();
02038 case JS_FUNCTION_TYPE:
02039 return Heap::function_symbol();
02040 default:
02041
02042
02043 return Heap::object_symbol();
02044 }
02045 }
02046
02047
02048 static Object* Runtime_StringToNumber(Arguments args) {
02049 NoHandleAllocation ha;
02050 ASSERT(args.length() == 1);
02051 CONVERT_CHECKED(String, subject, args[0]);
02052 subject->TryFlatten();
02053 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
02054 }
02055
02056
02057 static Object* Runtime_StringFromCharCodeArray(Arguments args) {
02058 NoHandleAllocation ha;
02059 ASSERT(args.length() == 1);
02060
02061 CONVERT_CHECKED(JSArray, codes, args[0]);
02062 int length = Smi::cast(codes->length())->value();
02063
02064
02065 int i;
02066 for (i = 0; i < length; i++) {
02067 Object* element = codes->GetElement(i);
02068 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
02069 if ((chr & 0xffff) > String::kMaxAsciiCharCode)
02070 break;
02071 }
02072
02073 Object* object = NULL;
02074 if (i == length) {
02075 object = Heap::AllocateRawAsciiString(length);
02076 } else {
02077 object = Heap::AllocateRawTwoByteString(length);
02078 }
02079
02080 if (object->IsFailure()) return object;
02081 String* result = String::cast(object);
02082 for (int i = 0; i < length; i++) {
02083 Object* element = codes->GetElement(i);
02084 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
02085 result->Set(i, chr & 0xffff);
02086 }
02087 return result;
02088 }
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103 static bool IsNotEscaped(uint16_t character) {
02104
02105 ASSERT(character < 256);
02106 static const char kNotEscaped[256] = {
02107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
02110 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
02111 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
02112 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
02113 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
02114 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
02115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02123 };
02124 return kNotEscaped[character] != 0;
02125 }
02126
02127
02128 static Object* Runtime_URIEscape(Arguments args) {
02129 const char hex_chars[] = "0123456789ABCDEF";
02130 NoHandleAllocation ha;
02131 ASSERT(args.length() == 1);
02132 CONVERT_CHECKED(String, source, args[0]);
02133
02134 source->TryFlatten();
02135
02136 int escaped_length = 0;
02137 int length = source->length();
02138 {
02139 Access<StringInputBuffer> buffer(&string_input_buffer);
02140 buffer->Reset(source);
02141 while (buffer->has_more()) {
02142 uint16_t character = buffer->GetNext();
02143 if (character >= 256) {
02144 escaped_length += 6;
02145 } else if (IsNotEscaped(character)) {
02146 escaped_length++;
02147 } else {
02148 escaped_length += 3;
02149 }
02150
02151 if (!Smi::IsValid(escaped_length)) {
02152 Top::context()->mark_out_of_memory();
02153 return Failure::OutOfMemoryException();
02154 }
02155 }
02156 }
02157
02158 if (escaped_length == length) {
02159 return source;
02160 }
02161 Object* o = Heap::AllocateRawAsciiString(escaped_length);
02162 if (o->IsFailure()) return o;
02163 String* destination = String::cast(o);
02164 int dest_position = 0;
02165
02166 Access<StringInputBuffer> buffer(&string_input_buffer);
02167 buffer->Rewind();
02168 while (buffer->has_more()) {
02169 uint16_t character = buffer->GetNext();
02170 if (character >= 256) {
02171 destination->Set(dest_position, '%');
02172 destination->Set(dest_position+1, 'u');
02173 destination->Set(dest_position+2, hex_chars[character >> 12]);
02174 destination->Set(dest_position+3, hex_chars[(character >> 8) & 0xf]);
02175 destination->Set(dest_position+4, hex_chars[(character >> 4) & 0xf]);
02176 destination->Set(dest_position+5, hex_chars[character & 0xf]);
02177 dest_position += 6;
02178 } else if (IsNotEscaped(character)) {
02179 destination->Set(dest_position, character);
02180 dest_position++;
02181 } else {
02182 destination->Set(dest_position, '%');
02183 destination->Set(dest_position+1, hex_chars[character >> 4]);
02184 destination->Set(dest_position+2, hex_chars[character & 0xf]);
02185 dest_position += 3;
02186 }
02187 }
02188 return destination;
02189 }
02190
02191
02192 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
02193 static const signed char kHexValue['g'] = {
02194 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
02195 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
02196 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
02197 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
02198 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
02199 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
02200 -1, 10, 11, 12, 13, 14, 15 };
02201
02202 if (character1 > 'f') return -1;
02203 int hi = kHexValue[character1];
02204 if (hi == -1) return -1;
02205 if (character2 > 'f') return -1;
02206 int lo = kHexValue[character2];
02207 if (lo == -1) return -1;
02208 return (hi << 4) + lo;
02209 }
02210
02211
02212 static inline int Unescape(String* source, int i, int length, int* step) {
02213 uint16_t character = source->Get(i);
02214 int32_t hi, lo;
02215 if (character == '%' &&
02216 i <= length - 6 &&
02217 source->Get(i + 1) == 'u' &&
02218 (hi = TwoDigitHex(source->Get(i + 2), source->Get(i + 3))) != -1 &&
02219 (lo = TwoDigitHex(source->Get(i + 4), source->Get(i + 5))) != -1) {
02220 *step = 6;
02221 return (hi << 8) + lo;
02222 } else if (character == '%' &&
02223 i <= length - 3 &&
02224 (lo = TwoDigitHex(source->Get(i + 1), source->Get(i + 2))) != -1) {
02225 *step = 3;
02226 return lo;
02227 } else {
02228 *step = 1;
02229 return character;
02230 }
02231 }
02232
02233
02234 static Object* Runtime_URIUnescape(Arguments args) {
02235 NoHandleAllocation ha;
02236 ASSERT(args.length() == 1);
02237 CONVERT_CHECKED(String, source, args[0]);
02238
02239 source->TryFlatten();
02240
02241 bool ascii = true;
02242 int length = source->length();
02243
02244 int unescaped_length = 0;
02245 for (int i = 0; i < length; unescaped_length++) {
02246 int step;
02247 if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode)
02248 ascii = false;
02249 i += step;
02250 }
02251
02252
02253 if (unescaped_length == length)
02254 return source;
02255
02256 Object* o = ascii ?
02257 Heap::AllocateRawAsciiString(unescaped_length) :
02258 Heap::AllocateRawTwoByteString(unescaped_length);
02259 if (o->IsFailure()) return o;
02260 String* destination = String::cast(o);
02261
02262 int dest_position = 0;
02263 for (int i = 0; i < length; dest_position++) {
02264 int step;
02265 destination->Set(dest_position, Unescape(source, i, length, &step));
02266 i += step;
02267 }
02268 return destination;
02269 }
02270
02271
02272 static Object* Runtime_StringParseInt(Arguments args) {
02273 NoHandleAllocation ha;
02274
02275 CONVERT_CHECKED(String, s, args[0]);
02276 CONVERT_DOUBLE_CHECKED(n, args[1]);
02277 int radix = FastD2I(n);
02278
02279 s->TryFlatten();
02280
02281 int len = s->length();
02282 int i;
02283
02284
02285 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
02286 if (i == len) return Heap::nan_value();
02287
02288
02289 int sign = 1;
02290 if (s->Get(i) == '-') {
02291 sign = -1;
02292 i++;
02293 } else if (s->Get(i) == '+') {
02294 i++;
02295 }
02296
02297
02298 if (radix == 0) {
02299 radix = 10;
02300 if (i < len && s->Get(i) == '0') {
02301 radix = 8;
02302 if (i + 1 < len) {
02303 int c = s->Get(i + 1);
02304 if (c == 'x' || c == 'X') {
02305 radix = 16;
02306 i += 2;
02307 }
02308 }
02309 }
02310 } else if (radix == 16) {
02311
02312 if (i + 1 < len && s->Get(i) == '0') {
02313 int c = s->Get(i + 1);
02314 if (c == 'x' || c == 'X') i += 2;
02315 }
02316 }
02317
02318 RUNTIME_ASSERT(2 <= radix && radix <= 36);
02319 double value;
02320 int end_index = StringToInt(s, i, radix, &value);
02321 if (end_index != i) {
02322 return Heap::NumberFromDouble(sign * value);
02323 }
02324 return Heap::nan_value();
02325 }
02326
02327
02328 static Object* Runtime_StringParseFloat(Arguments args) {
02329 NoHandleAllocation ha;
02330 CONVERT_CHECKED(String, str, args[0]);
02331
02332
02333 double value = StringToDouble(str, ALLOW_TRAILING_JUNK, OS::nan_value());
02334
02335
02336 return Heap::NumberFromDouble(value);
02337 }
02338
02339
02340 static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
02341 static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
02342
02343
02344 template <class Converter>
02345 static Object* ConvertCase(Arguments args,
02346 unibrow::Mapping<Converter, 128>* mapping) {
02347 NoHandleAllocation ha;
02348
02349 CONVERT_CHECKED(String, s, args[0]);
02350 int raw_string_length = s->length();
02351
02352 if (raw_string_length == 0) return s;
02353 int length = raw_string_length;
02354
02355 s->TryFlatten();
02356
02357
02358
02359
02360
02361
02362
02363 try_convert:
02364
02365
02366
02367
02368
02369
02370
02371 Object* o = s->IsAsciiRepresentation()
02372 ? Heap::AllocateRawAsciiString(length)
02373 : Heap::AllocateRawTwoByteString(length);
02374 if (o->IsFailure()) return o;
02375 String* result = String::cast(o);
02376 bool has_changed_character = false;
02377
02378
02379
02380 Access<StringInputBuffer> buffer(&string_input_buffer);
02381 buffer->Reset(s);
02382 unibrow::uchar chars[unibrow::kMaxCaseConvertedSize];
02383 int i = 0;
02384
02385 uc32 current = buffer->GetNext();
02386 while (i < length) {
02387 bool has_next = buffer->has_more();
02388 uc32 next = has_next ? buffer->GetNext() : 0;
02389 int char_length = mapping->get(current, next, chars);
02390 if (char_length == 0) {
02391
02392 result->Set(i, current);
02393 i++;
02394 } else if (char_length == 1) {
02395
02396 ASSERT(static_cast<uc32>(chars[0]) != current);
02397 result->Set(i, chars[0]);
02398 has_changed_character = true;
02399 i++;
02400 } else if (length == raw_string_length) {
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412 int next_length = 0;
02413 if (has_next) {
02414 next_length = mapping->get(next, 0, chars);
02415 if (next_length == 0) next_length = 1;
02416 }
02417 int current_length = i + char_length + next_length;
02418 while (buffer->has_more()) {
02419 current = buffer->GetNext();
02420
02421
02422
02423
02424 int char_length = mapping->get(current, 0, chars);
02425 if (char_length == 0) char_length = 1;
02426 current_length += char_length;
02427 }
02428 length = current_length;
02429 goto try_convert;
02430 } else {
02431 for (int j = 0; j < char_length; j++) {
02432 result->Set(i, chars[j]);
02433 i++;
02434 }
02435 has_changed_character = true;
02436 }
02437 current = next;
02438 }
02439 if (has_changed_character) {
02440 return result;
02441 } else {
02442
02443
02444
02445
02446 return s;
02447 }
02448 }
02449
02450
02451 static Object* Runtime_StringToLowerCase(Arguments args) {
02452 return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping);
02453 }
02454
02455
02456 static Object* Runtime_StringToUpperCase(Arguments args) {
02457 return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping);
02458 }
02459
02460
02461 static Object* Runtime_ConsStringFst(Arguments args) {
02462 NoHandleAllocation ha;
02463
02464 CONVERT_CHECKED(ConsString, str, args[0]);
02465 return str->first();
02466 }
02467
02468
02469 static Object* Runtime_ConsStringSnd(Arguments args) {
02470 NoHandleAllocation ha;
02471
02472 CONVERT_CHECKED(ConsString, str, args[0]);
02473 return str->second();
02474 }
02475
02476
02477 static Object* Runtime_NumberToString(Arguments args) {
02478 NoHandleAllocation ha;
02479 ASSERT(args.length() == 1);
02480
02481 Object* number = args[0];
02482 RUNTIME_ASSERT(number->IsNumber());
02483
02484 Object* cached = Heap::GetNumberStringCache(number);
02485 if (cached != Heap::undefined_value()) {
02486 return cached;
02487 }
02488
02489 char arr[100];
02490 Vector<char> buffer(arr, ARRAY_SIZE(arr));
02491 const char* str;
02492 if (number->IsSmi()) {
02493 int num = Smi::cast(number)->value();
02494 str = IntToCString(num, buffer);
02495 } else {
02496 double num = HeapNumber::cast(number)->value();
02497 str = DoubleToCString(num, buffer);
02498 }
02499 Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
02500
02501 if (!result->IsFailure()) {
02502 Heap::SetNumberStringCache(number, String::cast(result));
02503 }
02504 return result;
02505 }
02506
02507
02508 static Object* Runtime_NumberToInteger(Arguments args) {
02509 NoHandleAllocation ha;
02510 ASSERT(args.length() == 1);
02511
02512 Object* obj = args[0];
02513 if (obj->IsSmi()) return obj;
02514 CONVERT_DOUBLE_CHECKED(number, obj);
02515 return Heap::NumberFromDouble(DoubleToInteger(number));
02516 }
02517
02518
02519 static Object* Runtime_NumberToJSUint32(Arguments args) {
02520 NoHandleAllocation ha;
02521 ASSERT(args.length() == 1);
02522
02523 Object* obj = args[0];
02524 if (obj->IsSmi() && Smi::cast(obj)->value() >= 0) return obj;
02525 CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, obj);
02526 return Heap::NumberFromUint32(number);
02527 }
02528
02529
02530 static Object* Runtime_NumberToJSInt32(Arguments args) {
02531 NoHandleAllocation ha;
02532 ASSERT(args.length() == 1);
02533
02534 Object* obj = args[0];
02535 if (obj->IsSmi()) return obj;
02536 CONVERT_DOUBLE_CHECKED(number, obj);
02537 return Heap::NumberFromInt32(DoubleToInt32(number));
02538 }
02539
02540
02541 static Object* Runtime_NumberAdd(Arguments args) {
02542 NoHandleAllocation ha;
02543 ASSERT(args.length() == 2);
02544
02545 CONVERT_DOUBLE_CHECKED(x, args[0]);
02546 CONVERT_DOUBLE_CHECKED(y, args[1]);
02547 return Heap::AllocateHeapNumber(x + y);
02548 }
02549
02550
02551 static Object* Runtime_NumberSub(Arguments args) {
02552 NoHandleAllocation ha;
02553 ASSERT(args.length() == 2);
02554
02555 CONVERT_DOUBLE_CHECKED(x, args[0]);
02556 CONVERT_DOUBLE_CHECKED(y, args[1]);
02557 return Heap::AllocateHeapNumber(x - y);
02558 }
02559
02560
02561 static Object* Runtime_NumberMul(Arguments args) {
02562 NoHandleAllocation ha;
02563 ASSERT(args.length() == 2);
02564
02565 CONVERT_DOUBLE_CHECKED(x, args[0]);
02566 CONVERT_DOUBLE_CHECKED(y, args[1]);
02567 return Heap::AllocateHeapNumber(x * y);
02568 }
02569
02570
02571 static Object* Runtime_NumberUnaryMinus(Arguments args) {
02572 NoHandleAllocation ha;
02573 ASSERT(args.length() == 1);
02574
02575 CONVERT_DOUBLE_CHECKED(x, args[0]);
02576 return Heap::AllocateHeapNumber(-x);
02577 }
02578
02579
02580 static Object* Runtime_NumberDiv(Arguments args) {
02581 NoHandleAllocation ha;
02582 ASSERT(args.length() == 2);
02583
02584 CONVERT_DOUBLE_CHECKED(x, args[0]);
02585 CONVERT_DOUBLE_CHECKED(y, args[1]);
02586 return Heap::NewNumberFromDouble(x / y);
02587 }
02588
02589
02590 static Object* Runtime_NumberMod(Arguments args) {
02591 NoHandleAllocation ha;
02592 ASSERT(args.length() == 2);
02593
02594 CONVERT_DOUBLE_CHECKED(x, args[0]);
02595 CONVERT_DOUBLE_CHECKED(y, args[1]);
02596
02597 #ifdef WIN32
02598
02599
02600
02601 if (!(isfinite(x) && (!isfinite(y) && !isnan(y))) &&
02602 !(x == 0 && (y != 0 && isfinite(y))))
02603 #endif
02604 x = fmod(x, y);
02605
02606 return Heap::NewNumberFromDouble(x);
02607 }
02608
02609
02610 static Object* Runtime_StringAdd(Arguments args) {
02611 NoHandleAllocation ha;
02612 ASSERT(args.length() == 2);
02613
02614 CONVERT_CHECKED(String, str1, args[0]);
02615 CONVERT_CHECKED(String, str2, args[1]);
02616 int len1 = str1->length();
02617 int len2 = str2->length();
02618 if (len1 == 0) return str2;
02619 if (len2 == 0) return str1;
02620 int length_sum = len1 + len2;
02621
02622
02623 if (length_sum > Smi::kMaxValue || length_sum < 0) {
02624 Top::context()->mark_out_of_memory();
02625 return Failure::OutOfMemoryException();
02626 }
02627 return Heap::AllocateConsString(str1, str2);
02628 }
02629
02630
02631 template<typename sinkchar>
02632 static inline void StringBuilderConcatHelper(String* special,
02633 sinkchar* sink,
02634 FixedArray* fixed_array,
02635 int array_length) {
02636 int position = 0;
02637 for (int i = 0; i < array_length; i++) {
02638 Object* element = fixed_array->get(i);
02639 if (element->IsSmi()) {
02640 int len = Smi::cast(element)->value();
02641 int pos = len >> 11;
02642 len &= 0x7ff;
02643 String::WriteToFlat(special, sink + position, pos, pos + len);
02644 position += len;
02645 } else {
02646 String* string = String::cast(element);
02647 int element_length = string->length();
02648 String::WriteToFlat(string, sink + position, 0, element_length);
02649 position += element_length;
02650 }
02651 }
02652 }
02653
02654
02655 static Object* Runtime_StringBuilderConcat(Arguments args) {
02656 NoHandleAllocation ha;
02657 ASSERT(args.length() == 2);
02658 CONVERT_CHECKED(JSArray, array, args[0]);
02659 CONVERT_CHECKED(String, special, args[1]);
02660 int special_length = special->length();
02661 Object* smi_array_length = array->length();
02662 if (!smi_array_length->IsSmi()) {
02663 Top::context()->mark_out_of_memory();
02664 return Failure::OutOfMemoryException();
02665 }
02666 int array_length = Smi::cast(smi_array_length)->value();
02667 if (!array->HasFastElements()) {
02668 return Top::Throw(Heap::illegal_argument_symbol());
02669 }
02670 FixedArray* fixed_array = FixedArray::cast(array->elements());
02671 if (fixed_array->length() < array_length) {
02672 array_length = fixed_array->length();
02673 }
02674
02675 if (array_length == 0) {
02676 return Heap::empty_string();
02677 } else if (array_length == 1) {
02678 Object* first = fixed_array->get(0);
02679 if (first->IsString()) return first;
02680 }
02681
02682 bool ascii = special->IsAsciiRepresentation();
02683 int position = 0;
02684 for (int i = 0; i < array_length; i++) {
02685 Object* elt = fixed_array->get(i);
02686 if (elt->IsSmi()) {
02687 int len = Smi::cast(elt)->value();
02688 int pos = len >> 11;
02689 len &= 0x7ff;
02690 if (pos + len > special_length) {
02691 return Top::Throw(Heap::illegal_argument_symbol());
02692 }
02693 position += len;
02694 } else if (elt->IsString()) {
02695 String* element = String::cast(elt);
02696 int element_length = element->length();
02697 if (!Smi::IsValid(element_length + position)) {
02698 Top::context()->mark_out_of_memory();
02699 return Failure::OutOfMemoryException();
02700 }
02701 position += element_length;
02702 if (ascii && !element->IsAsciiRepresentation()) {
02703 ascii = false;
02704 }
02705 } else {
02706 return Top::Throw(Heap::illegal_argument_symbol());
02707 }
02708 }
02709
02710 int length = position;
02711 Object* object;
02712
02713 if (ascii) {
02714 object = Heap::AllocateRawAsciiString(length);
02715 if (object->IsFailure()) return object;
02716 SeqAsciiString* answer = SeqAsciiString::cast(object);
02717 StringBuilderConcatHelper(special,
02718 answer->GetChars(),
02719 fixed_array,
02720 array_length);
02721 return answer;
02722 } else {
02723 object = Heap::AllocateRawTwoByteString(length);
02724 if (object->IsFailure()) return object;
02725 SeqTwoByteString* answer = SeqTwoByteString::cast(object);
02726 StringBuilderConcatHelper(special,
02727 answer->GetChars(),
02728 fixed_array,
02729 array_length);
02730 return answer;
02731 }
02732 }
02733
02734
02735 static Object* Runtime_NumberOr(Arguments args) {
02736 NoHandleAllocation ha;
02737 ASSERT(args.length() == 2);
02738
02739 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
02740 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
02741 return Heap::NumberFromInt32(x | y);
02742 }
02743
02744
02745 static Object* Runtime_NumberAnd(Arguments args) {
02746 NoHandleAllocation ha;
02747 ASSERT(args.length() == 2);
02748
02749 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
02750 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
02751 return Heap::NumberFromInt32(x & y);
02752 }
02753
02754
02755 static Object* Runtime_NumberXor(Arguments args) {
02756 NoHandleAllocation ha;
02757 ASSERT(args.length() == 2);
02758
02759 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
02760 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
02761 return Heap::NumberFromInt32(x ^ y);
02762 }
02763
02764
02765 static Object* Runtime_NumberNot(Arguments args) {
02766 NoHandleAllocation ha;
02767 ASSERT(args.length() == 1);
02768
02769 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
02770 return Heap::NumberFromInt32(~x);
02771 }
02772
02773
02774 static Object* Runtime_NumberShl(Arguments args) {
02775 NoHandleAllocation ha;
02776 ASSERT(args.length() == 2);
02777
02778 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
02779 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
02780 return Heap::NumberFromInt32(x << (y & 0x1f));
02781 }
02782
02783
02784 static Object* Runtime_NumberShr(Arguments args) {
02785 NoHandleAllocation ha;
02786 ASSERT(args.length() == 2);
02787
02788 CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
02789 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
02790 return Heap::NumberFromUint32(x >> (y & 0x1f));
02791 }
02792
02793
02794 static Object* Runtime_NumberSar(Arguments args) {
02795 NoHandleAllocation ha;
02796 ASSERT(args.length() == 2);
02797
02798 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
02799 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
02800 return Heap::NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
02801 }
02802
02803
02804 static Object* Runtime_NumberEquals(Arguments args) {
02805 NoHandleAllocation ha;
02806 ASSERT(args.length() == 2);
02807
02808 CONVERT_DOUBLE_CHECKED(x, args[0]);
02809 CONVERT_DOUBLE_CHECKED(y, args[1]);
02810 if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
02811 if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
02812 if (x == y) return Smi::FromInt(EQUAL);
02813 Object* result;
02814 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
02815 result = Smi::FromInt(EQUAL);
02816 } else {
02817 result = Smi::FromInt(NOT_EQUAL);
02818 }
02819 return result;
02820 }
02821
02822
02823 static Object* Runtime_StringEquals(Arguments args) {
02824 NoHandleAllocation ha;
02825 ASSERT(args.length() == 2);
02826
02827 CONVERT_CHECKED(String, x, args[0]);
02828 CONVERT_CHECKED(String, y, args[1]);
02829
02830 bool not_equal = !x->Equals(y);
02831
02832
02833
02834 ASSERT(not_equal == 0 || not_equal == 1);
02835 STATIC_CHECK(EQUAL == 0);
02836 STATIC_CHECK(NOT_EQUAL == 1);
02837 return Smi::FromInt(not_equal);
02838 }
02839
02840
02841 static Object* Runtime_NumberCompare(Arguments args) {
02842 NoHandleAllocation ha;
02843 ASSERT(args.length() == 3);
02844
02845 CONVERT_DOUBLE_CHECKED(x, args[0]);
02846 CONVERT_DOUBLE_CHECKED(y, args[1]);
02847 if (isnan(x) || isnan(y)) return args[2];
02848 if (x == y) return Smi::FromInt(EQUAL);
02849 if (isless(x, y)) return Smi::FromInt(LESS);
02850 return Smi::FromInt(GREATER);
02851 }
02852
02853
02854
02855
02856 static Object* Runtime_SmiLexicographicCompare(Arguments args) {
02857 NoHandleAllocation ha;
02858 ASSERT(args.length() == 2);
02859
02860
02861
02862 static int x_elms[10];
02863 static int y_elms[10];
02864
02865
02866 CONVERT_CHECKED(Smi, x, args[0]);
02867 CONVERT_CHECKED(Smi, y, args[1]);
02868 int x_value = x->value();
02869 int y_value = y->value();
02870
02871
02872 if (x_value == y_value) return Smi::FromInt(EQUAL);
02873
02874
02875
02876 if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value);
02877
02878
02879
02880
02881 if (x_value < 0 || y_value < 0) {
02882 if (y_value >= 0) return Smi::FromInt(LESS);
02883 if (x_value >= 0) return Smi::FromInt(GREATER);
02884 x_value = -x_value;
02885 y_value = -y_value;
02886 }
02887
02888
02889 int x_index = 0;
02890 int y_index = 0;
02891 while (x_value > 0) {
02892 x_elms[x_index++] = x_value % 10;
02893 x_value /= 10;
02894 }
02895 while (y_value > 0) {
02896 y_elms[y_index++] = y_value % 10;
02897 y_value /= 10;
02898 }
02899
02900
02901
02902 while (--x_index >= 0 && --y_index >= 0) {
02903 int diff = x_elms[x_index] - y_elms[y_index];
02904 if (diff != 0) return Smi::FromInt(diff);
02905 }
02906
02907
02908
02909
02910 return Smi::FromInt(x_index - y_index);
02911 }
02912
02913
02914 static Object* Runtime_StringCompare(Arguments args) {
02915 NoHandleAllocation ha;
02916 ASSERT(args.length() == 2);
02917
02918 CONVERT_CHECKED(String, x, args[0]);
02919 CONVERT_CHECKED(String, y, args[1]);
02920
02921
02922 if (x == y) return Smi::FromInt(EQUAL);
02923 if (y->length() == 0) {
02924 if (x->length() == 0) return Smi::FromInt(EQUAL);
02925 return Smi::FromInt(GREATER);
02926 } else if (x->length() == 0) {
02927 return Smi::FromInt(LESS);
02928 }
02929
02930 int d = x->Get(0) - y->Get(0);
02931 if (d < 0) return Smi::FromInt(LESS);
02932 else if (d > 0) return Smi::FromInt(GREATER);
02933
02934 x->TryFlatten();
02935 y->TryFlatten();
02936
02937 static StringInputBuffer bufx;
02938 static StringInputBuffer bufy;
02939 bufx.Reset(x);
02940 bufy.Reset(y);
02941 while (bufx.has_more() && bufy.has_more()) {
02942 int d = bufx.GetNext() - bufy.GetNext();
02943 if (d < 0) return Smi::FromInt(LESS);
02944 else if (d > 0) return Smi::FromInt(GREATER);
02945 }
02946
02947
02948 if (bufy.has_more()) return Smi::FromInt(LESS);
02949
02950 return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
02951 }
02952
02953
02954 static Object* Runtime_Math_abs(Arguments args) {
02955 NoHandleAllocation ha;
02956 ASSERT(args.length() == 1);
02957
02958 CONVERT_DOUBLE_CHECKED(x, args[0]);
02959 return Heap::AllocateHeapNumber(fabs(x));
02960 }
02961
02962
02963 static Object* Runtime_Math_acos(Arguments args) {
02964 NoHandleAllocation ha;
02965 ASSERT(args.length() == 1);
02966
02967 CONVERT_DOUBLE_CHECKED(x, args[0]);
02968 return Heap::AllocateHeapNumber(acos(x));
02969 }
02970
02971
02972 static Object* Runtime_Math_asin(Arguments args) {
02973 NoHandleAllocation ha;
02974 ASSERT(args.length() == 1);
02975
02976 CONVERT_DOUBLE_CHECKED(x, args[0]);
02977 return Heap::AllocateHeapNumber(asin(x));
02978 }
02979
02980
02981 static Object* Runtime_Math_atan(Arguments args) {
02982 NoHandleAllocation ha;
02983 ASSERT(args.length() == 1);
02984
02985 CONVERT_DOUBLE_CHECKED(x, args[0]);
02986 return Heap::AllocateHeapNumber(atan(x));
02987 }
02988
02989
02990 static Object* Runtime_Math_atan2(Arguments args) {
02991 NoHandleAllocation ha;
02992 ASSERT(args.length() == 2);
02993
02994 CONVERT_DOUBLE_CHECKED(x, args[0]);
02995 CONVERT_DOUBLE_CHECKED(y, args[1]);
02996 double result;
02997 if (isinf(x) && isinf(y)) {
02998
02999
03000
03001
03002 static double kPiDividedBy4 = 0.78539816339744830962;
03003 int multiplier = (x < 0) ? -1 : 1;
03004 if (y < 0) multiplier *= 3;
03005 result = multiplier * kPiDividedBy4;
03006 } else {
03007 result = atan2(x, y);
03008 }
03009 return Heap::AllocateHeapNumber(result);
03010 }
03011
03012
03013 static Object* Runtime_Math_ceil(Arguments args) {
03014 NoHandleAllocation ha;
03015 ASSERT(args.length() == 1);
03016
03017 CONVERT_DOUBLE_CHECKED(x, args[0]);
03018 return Heap::NumberFromDouble(ceiling(x));
03019 }
03020
03021
03022 static Object* Runtime_Math_cos(Arguments args) {
03023 NoHandleAllocation ha;
03024 ASSERT(args.length() == 1);
03025
03026 CONVERT_DOUBLE_CHECKED(x, args[0]);
03027 return Heap::AllocateHeapNumber(cos(x));
03028 }
03029
03030
03031 static Object* Runtime_Math_exp(Arguments args) {
03032 NoHandleAllocation ha;
03033 ASSERT(args.length() == 1);
03034
03035 CONVERT_DOUBLE_CHECKED(x, args[0]);
03036 return Heap::AllocateHeapNumber(exp(x));
03037 }
03038
03039
03040 static Object* Runtime_Math_floor(Arguments args) {
03041 NoHandleAllocation ha;
03042 ASSERT(args.length() == 1);
03043
03044 CONVERT_DOUBLE_CHECKED(x, args[0]);
03045 return Heap::NumberFromDouble(floor(x));
03046 }
03047
03048
03049 static Object* Runtime_Math_log(Arguments args) {
03050 NoHandleAllocation ha;
03051 ASSERT(args.length() == 1);
03052
03053 CONVERT_DOUBLE_CHECKED(x, args[0]);
03054 return Heap::AllocateHeapNumber(log(x));
03055 }
03056
03057
03058 static Object* Runtime_Math_pow(Arguments args) {
03059 NoHandleAllocation ha;
03060 ASSERT(args.length() == 2);
03061
03062 CONVERT_DOUBLE_CHECKED(x, args[0]);
03063 CONVERT_DOUBLE_CHECKED(y, args[1]);
03064 if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
03065 return Heap::nan_value();
03066 } else if (y == 0) {
03067 return Smi::FromInt(1);
03068 } else {
03069 return Heap::AllocateHeapNumber(pow(x, y));
03070 }
03071 }
03072
03073
03074
03075 static Object* Runtime_Math_random(Arguments args) {
03076 NoHandleAllocation ha;
03077 ASSERT(args.length() == 0);
03078
03079
03080
03081
03082
03083
03084 double lo = static_cast<double>(random()) / (RAND_MAX + 1.0);
03085 double hi = static_cast<double>(random());
03086 double result = (hi + lo) / (RAND_MAX + 1.0);
03087 ASSERT(result >= 0 && result < 1);
03088 return Heap::AllocateHeapNumber(result);
03089 }
03090
03091
03092 static Object* Runtime_Math_round(Arguments args) {
03093 NoHandleAllocation ha;
03094 ASSERT(args.length() == 1);
03095
03096 CONVERT_DOUBLE_CHECKED(x, args[0]);
03097 if (signbit(x) && x >= -0.5) return Heap::minus_zero_value();
03098 return Heap::NumberFromDouble(floor(x + 0.5));
03099 }
03100
03101
03102 static Object* Runtime_Math_sin(Arguments args) {
03103 NoHandleAllocation ha;
03104 ASSERT(args.length() == 1);
03105
03106 CONVERT_DOUBLE_CHECKED(x, args[0]);
03107 return Heap::AllocateHeapNumber(sin(x));
03108 }
03109
03110
03111 static Object* Runtime_Math_sqrt(Arguments args) {
03112 NoHandleAllocation ha;
03113 ASSERT(args.length() == 1);
03114
03115 CONVERT_DOUBLE_CHECKED(x, args[0]);
03116 return Heap::AllocateHeapNumber(sqrt(x));
03117 }
03118
03119
03120 static Object* Runtime_Math_tan(Arguments args) {
03121 NoHandleAllocation ha;
03122 ASSERT(args.length() == 1);
03123
03124 CONVERT_DOUBLE_CHECKED(x, args[0]);
03125 return Heap::AllocateHeapNumber(tan(x));
03126 }
03127
03128
03129
03130
03131
03132 static Object* Runtime_NewArguments(Arguments args) {
03133 NoHandleAllocation ha;
03134 ASSERT(args.length() == 1);
03135
03136
03137 CONVERT_CHECKED(JSFunction, callee, args[0]);
03138
03139
03140 JavaScriptFrameIterator it;
03141 it.AdvanceToArgumentsFrame();
03142 JavaScriptFrame* frame = it.frame();
03143
03144 const int length = frame->GetProvidedParametersCount();
03145 Object* result = Heap::AllocateArgumentsObject(callee, length);
03146 if (result->IsFailure()) return result;
03147 if (length > 0) {
03148 Object* obj = Heap::AllocateFixedArray(length);
03149 if (obj->IsFailure()) return obj;
03150 FixedArray* array = FixedArray::cast(obj);
03151 ASSERT(array->length() == length);
03152 WriteBarrierMode mode = array->GetWriteBarrierMode();
03153 for (int i = 0; i < length; i++) {
03154 array->set(i, frame->GetParameter(i), mode);
03155 }
03156 JSObject::cast(result)->set_elements(array);
03157 }
03158 return result;
03159 }
03160
03161
03162 static Object* Runtime_NewArgumentsFast(Arguments args) {
03163 NoHandleAllocation ha;
03164 ASSERT(args.length() == 3);
03165
03166 JSFunction* callee = JSFunction::cast(args[0]);
03167 Object** parameters = reinterpret_cast<Object**>(args[1]);
03168 const int length = Smi::cast(args[2])->value();
03169
03170 Object* result = Heap::AllocateArgumentsObject(callee, length);
03171 if (result->IsFailure()) return result;
03172 ASSERT(Heap::InNewSpace(result));
03173
03174
03175 if (length > 0) {
03176
03177 Object* obj = Heap::AllocateRawFixedArray(length);
03178 if (obj->IsFailure()) return obj;
03179 reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map());
03180 FixedArray* array = FixedArray::cast(obj);
03181 array->set_length(length);
03182 WriteBarrierMode mode = array->GetWriteBarrierMode();
03183 for (int i = 0; i < length; i++) {
03184 array->set(i, *--parameters, mode);
03185 }
03186 JSObject::cast(result)->set_elements(FixedArray::cast(obj),
03187 SKIP_WRITE_BARRIER);
03188 }
03189 return result;
03190 }
03191
03192
03193 static Object* Runtime_NewClosure(Arguments args) {
03194 HandleScope scope;
03195 ASSERT(args.length() == 2);
03196 CONVERT_ARG_CHECKED(JSFunction, boilerplate, 0);
03197 CONVERT_ARG_CHECKED(Context, context, 1);
03198
03199 Handle<JSFunction> result =
03200 Factory::NewFunctionFromBoilerplate(boilerplate, context);
03201 return *result;
03202 }
03203
03204
03205 static Object* Runtime_NewObject(Arguments args) {
03206 NoHandleAllocation ha;
03207 ASSERT(args.length() == 1);
03208
03209 Object* constructor = args[0];
03210 if (constructor->IsJSFunction()) {
03211 JSFunction* function = JSFunction::cast(constructor);
03212
03213
03214 if (Debug::StepInActive()) {
03215 StackFrameIterator it;
03216 it.Advance();
03217 ASSERT(it.frame()->is_construct());
03218 it.Advance();
03219 if (it.frame()->fp() == Debug::step_in_fp()) {
03220 HandleScope scope;
03221 Debug::FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
03222 }
03223 }
03224
03225 if (function->has_initial_map() &&
03226 function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237 return Top::context()->global();
03238 }
03239 return Heap::AllocateJSObject(function);
03240 }
03241
03242 HandleScope scope;
03243 Handle<Object> cons(constructor);
03244
03245 Handle<Object> type_error =
03246 Factory::NewTypeError("not_constructor", HandleVector(&cons, 1));
03247 return Top::Throw(*type_error);
03248 }
03249
03250
03251 static Object* Runtime_LazyCompile(Arguments args) {
03252 HandleScope scope;
03253 ASSERT(args.length() == 1);
03254
03255 Handle<JSFunction> function = args.at<JSFunction>(0);
03256 #ifdef DEBUG
03257 if (FLAG_trace_lazy) {
03258 PrintF("[lazy: ");
03259 function->shared()->name()->Print();
03260 PrintF("]\n");
03261 }
03262 #endif
03263
03264
03265 ASSERT(!function->is_compiled());
03266 if (!CompileLazy(function, KEEP_EXCEPTION)) {
03267 return Failure::Exception();
03268 }
03269
03270 return function->code();
03271 }
03272
03273
03274 static Object* Runtime_GetCalledFunction(Arguments args) {
03275 HandleScope scope;
03276 ASSERT(args.length() == 0);
03277 StackFrameIterator it;
03278
03279 ASSERT(it.frame()->is_exit());
03280 it.Advance();
03281
03282 ASSERT(it.frame()->is_java_script());
03283 it.Advance();
03284
03285
03286 if (it.frame()->is_arguments_adaptor()) it.Advance();
03287
03288
03289 StandardFrame* frame = StandardFrame::cast(it.frame());
03290 int index = frame->ComputeExpressionsCount() - 1;
03291 Object* result = frame->GetExpression(index);
03292 return result;
03293 }
03294
03295
03296 static Object* Runtime_GetFunctionDelegate(Arguments args) {
03297 HandleScope scope;
03298 ASSERT(args.length() == 1);
03299 RUNTIME_ASSERT(!args[0]->IsJSFunction());
03300 return *Execution::GetFunctionDelegate(args.at<Object>(0));
03301 }
03302
03303
03304 static Object* Runtime_NewContext(Arguments args) {
03305 NoHandleAllocation ha;
03306 ASSERT(args.length() == 1);
03307
03308 CONVERT_CHECKED(JSFunction, function, args[0]);
03309 int length = ScopeInfo<>::NumberOfContextSlots(function->code());
03310 Object* result = Heap::AllocateFunctionContext(length, function);
03311 if (result->IsFailure()) return result;
03312
03313 Top::set_context(Context::cast(result));
03314
03315 return result;
03316 }
03317
03318
03319 static Object* Runtime_PushContext(Arguments args) {
03320 NoHandleAllocation ha;
03321 ASSERT(args.length() == 1);
03322
03323
03324 Object* object = args[0];
03325 if (!object->IsJSObject()) {
03326 object = object->ToObject();
03327 if (object->IsFailure()) {
03328 if (!Failure::cast(object)->IsInternalError()) return object;
03329 HandleScope scope;
03330 Handle<Object> handle(args[0]);
03331 Handle<Object> result =
03332 Factory::NewTypeError("with_expression", HandleVector(&handle, 1));
03333 return Top::Throw(*result);
03334 }
03335 }
03336
03337 Object* result =
03338 Heap::AllocateWithContext(Top::context(), JSObject::cast(object));
03339 if (result->IsFailure()) return result;
03340
03341 Top::set_context(Context::cast(result));
03342
03343 return result;
03344 }
03345
03346
03347 static Object* Runtime_LookupContext(Arguments args) {
03348 HandleScope scope;
03349 ASSERT(args.length() == 2);
03350
03351 CONVERT_ARG_CHECKED(Context, context, 0);
03352 CONVERT_ARG_CHECKED(String, name, 1);
03353
03354 int index;
03355 PropertyAttributes attributes;
03356 ContextLookupFlags flags = FOLLOW_CHAINS;
03357 Handle<Object> holder =
03358 context->Lookup(name, flags, &index, &attributes);
03359
03360 if (index < 0 && !holder.is_null()) {
03361 ASSERT(holder->IsJSObject());
03362 return *holder;
03363 }
03364
03365
03366 return Top::context()->global();
03367 }
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377 typedef uint64_t ObjectPair;
03378 static inline ObjectPair MakePair(Object* x, Object* y) {
03379 return reinterpret_cast<uint32_t>(x) |
03380 (reinterpret_cast<ObjectPair>(y) << 32);
03381 }
03382
03383
03384 static inline Object* Unhole(Object* x, PropertyAttributes attributes) {
03385 ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
03386 USE(attributes);
03387 return x->IsTheHole() ? Heap::undefined_value() : x;
03388 }
03389
03390
03391 static JSObject* ComputeReceiverForNonGlobal(JSObject* holder) {
03392 ASSERT(!holder->IsGlobalObject());
03393 Context* top = Top::context();
03394
03395 JSFunction* context_extension_function =
03396 top->global_context()->context_extension_function();
03397
03398
03399
03400
03401 Object* constructor = holder->map()->constructor();
03402 if (constructor != context_extension_function) return holder;
03403
03404
03405
03406 return top->global()->global_receiver();
03407 }
03408
03409
03410 static ObjectPair LoadContextSlotHelper(Arguments args, bool throw_error) {
03411 HandleScope scope;
03412 ASSERT(args.length() == 2);
03413
03414 if (!args[0]->IsContext() || !args[1]->IsString()) {
03415 return MakePair(IllegalOperation(), NULL);
03416 }
03417 Handle<Context> context = args.at<Context>(0);
03418 Handle<String> name = args.at<String>(1);
03419
03420 int index;
03421 PropertyAttributes attributes;
03422 ContextLookupFlags flags = FOLLOW_CHAINS;
03423 Handle<Object> holder =
03424 context->Lookup(name, flags, &index, &attributes);
03425
03426
03427
03428
03429 if (index >= 0) {
03430
03431
03432
03433 JSObject* receiver = Top::context()->global()->global_receiver();
03434 Object* value = (holder->IsContext())
03435 ? Context::cast(*holder)->get(index)
03436 : JSObject::cast(*holder)->GetElement(index);
03437 return MakePair(Unhole(value, attributes), receiver);
03438 }
03439
03440
03441 if (!holder.is_null() && holder->IsJSObject()) {
03442 ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name));
03443 JSObject* object = JSObject::cast(*holder);
03444 JSObject* receiver = (object->IsGlobalObject())
03445 ? GlobalObject::cast(object)->global_receiver()
03446 : ComputeReceiverForNonGlobal(object);
03447
03448
03449 Object* value = object->GetProperty(*name);
03450 return MakePair(value, receiver);
03451 }
03452
03453 if (throw_error) {
03454
03455 Handle<Object> reference_error =
03456 Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
03457 return MakePair(Top::Throw(*reference_error), NULL);
03458 } else {
03459
03460 return MakePair(Heap::undefined_value(), Heap::undefined_value());
03461 }
03462 }
03463
03464
03465 static ObjectPair Runtime_LoadContextSlot(Arguments args) {
03466 return LoadContextSlotHelper(args, true);
03467 }
03468
03469
03470 static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
03471 return LoadContextSlotHelper(args, false);
03472 }
03473
03474
03475 static Object* Runtime_StoreContextSlot(Arguments args) {
03476 HandleScope scope;
03477 ASSERT(args.length() == 3);
03478
03479 Handle<Object> value(args[0]);
03480 CONVERT_ARG_CHECKED(Context, context, 1);
03481 CONVERT_ARG_CHECKED(String, name, 2);
03482
03483 int index;
03484 PropertyAttributes attributes;
03485 ContextLookupFlags flags = FOLLOW_CHAINS;
03486 Handle<Object> holder =
03487 context->Lookup(name, flags, &index, &attributes);
03488
03489 if (index >= 0) {
03490 if (holder->IsContext()) {
03491
03492 if ((attributes & READ_ONLY) == 0) {
03493 Handle<Context>::cast(holder)->set(index, *value);
03494 }
03495 } else {
03496 ASSERT((attributes & READ_ONLY) == 0);
03497 Object* result =
03498 Handle<JSObject>::cast(holder)->SetElement(index, *value);
03499 USE(result);
03500 ASSERT(!result->IsFailure());
03501 }
03502 return *value;
03503 }
03504
03505
03506
03507 Handle<JSObject> context_ext;
03508
03509 if (!holder.is_null()) {
03510
03511 context_ext = Handle<JSObject>::cast(holder);
03512 } else {
03513
03514 ASSERT(attributes == ABSENT);
03515 attributes = NONE;
03516 context_ext = Handle<JSObject>(Top::context()->global());
03517 }
03518
03519
03520 if ((attributes & READ_ONLY) == 0) {
03521 Handle<Object> set = SetProperty(context_ext, name, value, attributes);
03522 if (set.is_null()) {
03523
03524
03525
03526 ASSERT(Top::has_pending_exception());
03527 return Failure::Exception();
03528 }
03529 }
03530 return *value;
03531 }
03532
03533
03534 static Object* Runtime_Throw(Arguments args) {
03535 HandleScope scope;
03536 ASSERT(args.length() == 1);
03537
03538 return Top::Throw(args[0]);
03539 }
03540
03541
03542 static Object* Runtime_ReThrow(Arguments args) {
03543 HandleScope scope;
03544 ASSERT(args.length() == 1);
03545
03546 return Top::ReThrow(args[0]);
03547 }
03548
03549
03550 static Object* Runtime_ThrowReferenceError(Arguments args) {
03551 HandleScope scope;
03552 ASSERT(args.length() == 1);
03553
03554 Handle<Object> name(args[0]);
03555 Handle<Object> reference_error =
03556 Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
03557 return Top::Throw(*reference_error);
03558 }
03559
03560
03561 static Object* Runtime_StackOverflow(Arguments args) {
03562 NoHandleAllocation na;
03563 return Top::StackOverflow();
03564 }
03565
03566
03567 static Object* RuntimePreempt(Arguments args) {
03568
03569 StackGuard::Continue(PREEMPT);
03570
03571 ContextSwitcher::PreemptionReceived();
03572
03573 {
03574 v8::Unlocker unlocker;
03575 Thread::YieldCPU();
03576 }
03577
03578 return Heap::undefined_value();
03579 }
03580
03581
03582 static Object* DebugBreakHelper() {
03583
03584 if (Debug::disable_break()) {
03585 return Heap::undefined_value();
03586 }
03587
03588
03589
03590
03591 JavaScriptFrameIterator it;
03592 JavaScriptFrame* frame = it.frame();
03593 Object* fun = frame->function();
03594 if (fun->IsJSFunction()) {
03595 GlobalObject* global = JSFunction::cast(fun)->context()->global();
03596 if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
03597 return Heap::undefined_value();
03598 }
03599 }
03600
03601
03602 StackGuard::Continue(DEBUGBREAK);
03603
03604 HandleScope scope;
03605
03606 EnterDebugger debugger;
03607 if (debugger.FailedToEnter()) {
03608 return Heap::undefined_value();
03609 }
03610
03611
03612 Debugger::OnDebugBreak(Factory::undefined_value());
03613
03614
03615 return Heap::undefined_value();
03616 }
03617
03618
03619 static Object* Runtime_DebugBreak(Arguments args) {
03620 ASSERT(args.length() == 0);
03621 return DebugBreakHelper();
03622 }
03623
03624
03625 static Object* Runtime_StackGuard(Arguments args) {
03626 ASSERT(args.length() == 1);
03627
03628
03629 if (StackGuard::IsStackOverflow()) return Runtime_StackOverflow(args);
03630
03631
03632
03633 if (StackGuard::IsDebugBreak()) DebugBreakHelper();
03634 if (StackGuard::IsPreempted()) RuntimePreempt(args);
03635 if (StackGuard::IsInterrupted()) {
03636
03637 StackGuard::Continue(INTERRUPT);
03638 return Top::StackOverflow();
03639 }
03640 return Heap::undefined_value();
03641 }
03642
03643
03644
03645
03646
03647 static void PrintString(String* str) {
03648
03649 if (str->length() > 0) {
03650 SmartPointer<char> s =
03651 str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
03652 PrintF("%s", *s);
03653 }
03654 }
03655
03656
03657 static void PrintObject(Object* obj) {
03658 if (obj->IsSmi()) {
03659 PrintF("%d", Smi::cast(obj)->value());
03660 } else if (obj->IsString() || obj->IsSymbol()) {
03661 PrintString(String::cast(obj));
03662 } else if (obj->IsNumber()) {
03663 PrintF("%g", obj->Number());
03664 } else if (obj->IsFailure()) {
03665 PrintF("<failure>");
03666 } else if (obj->IsUndefined()) {
03667 PrintF("<undefined>");
03668 } else if (obj->IsNull()) {
03669 PrintF("<null>");
03670 } else if (obj->IsTrue()) {
03671 PrintF("<true>");
03672 } else if (obj->IsFalse()) {
03673 PrintF("<false>");
03674 } else {
03675 PrintF("%p", obj);
03676 }
03677 }
03678
03679
03680 static int StackSize() {
03681 int n = 0;
03682 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
03683 return n;
03684 }
03685
03686
03687 static void PrintTransition(Object* result) {
03688
03689 { const int nmax = 80;
03690 int n = StackSize();
03691 if (n <= nmax)
03692 PrintF("%4d:%*s", n, n, "");
03693 else
03694 PrintF("%4d:%*s", n, nmax, "...");
03695 }
03696
03697 if (result == NULL) {
03698
03699 JavaScriptFrameIterator it;
03700 JavaScriptFrame* frame = it.frame();
03701 if (frame->IsConstructor()) PrintF("new ");
03702
03703 Object* fun = frame->function();
03704 if (fun->IsJSFunction()) {
03705 PrintObject(JSFunction::cast(fun)->shared()->name());
03706 } else {
03707 PrintObject(fun);
03708 }
03709
03710
03711
03712 PrintF("(this=");
03713 PrintObject(frame->receiver());
03714 const int length = frame->GetProvidedParametersCount();
03715 for (int i = 0; i < length; i++) {
03716 PrintF(", ");
03717 PrintObject(frame->GetParameter(i));
03718 }
03719 PrintF(") {\n");
03720
03721 } else {
03722
03723 PrintF("} -> ");
03724 PrintObject(result);
03725 PrintF("\n");
03726 }
03727 }
03728
03729
03730 static Object* Runtime_TraceEnter(Arguments args) {
03731 ASSERT(args.length() == 0);
03732 NoHandleAllocation ha;
03733 PrintTransition(NULL);
03734 return Heap::undefined_value();
03735 }
03736
03737
03738 static Object* Runtime_TraceExit(Arguments args) {
03739 NoHandleAllocation ha;
03740 PrintTransition(args[0]);
03741 return args[0];
03742 }
03743
03744
03745 static Object* Runtime_DebugPrint(Arguments args) {
03746 NoHandleAllocation ha;
03747 ASSERT(args.length() == 1);
03748
03749 #ifdef DEBUG
03750 if (args[0]->IsString()) {
03751
03752
03753 JavaScriptFrameIterator it;
03754 JavaScriptFrame* frame = it.frame();
03755 PrintF("fp = %p, sp = %p, pp = %p: ",
03756 frame->fp(), frame->sp(), frame->pp());
03757 } else {
03758 PrintF("DebugPrint: ");
03759 }
03760 args[0]->Print();
03761 #else
03762
03763 args[0]->ShortPrint();
03764 #endif
03765 PrintF("\n");
03766 Flush();
03767
03768 return args[0];
03769 }
03770
03771
03772 static Object* Runtime_DebugTrace(Arguments args) {
03773 ASSERT(args.length() == 0);
03774 NoHandleAllocation ha;
03775 Top::PrintStack();
03776 return Heap::undefined_value();
03777 }
03778
03779
03780 static Object* Runtime_DateCurrentTime(Arguments args) {
03781 NoHandleAllocation ha;
03782 ASSERT(args.length() == 0);
03783
03784
03785
03786
03787
03788 double millis = floor(OS::TimeCurrentMillis());
03789 return Heap::NumberFromDouble(millis);
03790 }
03791
03792
03793 static Object* Runtime_DateParseString(Arguments args) {
03794 HandleScope scope;
03795 ASSERT(args.length() == 1);
03796
03797 CONVERT_CHECKED(String, string_object, args[0]);
03798
03799 Handle<String> str(string_object);
03800 Handle<FixedArray> output = Factory::NewFixedArray(DateParser::OUTPUT_SIZE);
03801 if (DateParser::Parse(*str, *output)) {
03802 return *Factory::NewJSArrayWithElements(output);
03803 } else {
03804 return *Factory::null_value();
03805 }
03806 }
03807
03808
03809 static Object* Runtime_DateLocalTimezone(Arguments args) {
03810 NoHandleAllocation ha;
03811 ASSERT(args.length() == 1);
03812
03813 CONVERT_DOUBLE_CHECKED(x, args[0]);
03814 char* zone = OS::LocalTimezone(x);
03815 return Heap::AllocateStringFromUtf8(CStrVector(zone));
03816 }
03817
03818
03819 static Object* Runtime_DateLocalTimeOffset(Arguments args) {
03820 NoHandleAllocation ha;
03821 ASSERT(args.length() == 0);
03822
03823 return Heap::NumberFromDouble(OS::LocalTimeOffset());
03824 }
03825
03826
03827 static Object* Runtime_DateDaylightSavingsOffset(Arguments args) {
03828 NoHandleAllocation ha;
03829 ASSERT(args.length() == 1);
03830
03831 CONVERT_DOUBLE_CHECKED(x, args[0]);
03832 return Heap::NumberFromDouble(OS::DaylightSavingsOffset(x));
03833 }
03834
03835
03836 static Object* Runtime_NumberIsFinite(Arguments args) {
03837 NoHandleAllocation ha;
03838 ASSERT(args.length() == 1);
03839
03840 CONVERT_DOUBLE_CHECKED(value, args[0]);
03841 Object* result;
03842 if (isnan(value) || (fpclassify(value) == FP_INFINITE)) {
03843 result = Heap::false_value();
03844 } else {
03845 result = Heap::true_value();
03846 }
03847 return result;
03848 }
03849
03850
03851 static Object* EvalContext() {
03852
03853
03854
03855 StackFrameLocator locator;
03856 JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
03857
03858
03859
03860
03861
03862 HandleScope scope;
03863 if (!ScopeInfo<>::SupportsEval(frame->FindCode())) {
03864
03865
03866 return *Top::global_context();
03867 }
03868
03869
03870 Handle<Context> caller(Context::cast(frame->context()));
03871
03872
03873
03874 Handle<Context> target = Top::global_context();
03875 if (caller->global_context() == *target) return *caller;
03876
03877
03878
03879
03880 Handle<JSFunction> closure = Factory::NewFunction(Factory::empty_symbol(),
03881 Factory::undefined_value());
03882 closure->set_context(*caller);
03883
03884
03885
03886
03887
03888
03889
03890 Handle<Context> adaptor =
03891 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, closure);
03892 adaptor->set_extension(target->global());
03893 return *adaptor;
03894 }
03895
03896
03897 static Object* Runtime_EvalReceiver(Arguments args) {
03898 StackFrameLocator locator;
03899 return locator.FindJavaScriptFrame(1)->receiver();
03900 }
03901
03902
03903 static Object* Runtime_GlobalReceiver(Arguments args) {
03904 ASSERT(args.length() == 1);
03905 Object* global = args[0];
03906 if (!global->IsJSGlobalObject()) return Heap::null_value();
03907 return JSGlobalObject::cast(global)->global_receiver();
03908 }
03909
03910
03911 static Object* Runtime_CompileString(Arguments args) {
03912 HandleScope scope;
03913 ASSERT(args.length() == 3);
03914 CONVERT_ARG_CHECKED(String, source, 0);
03915 CONVERT_ARG_CHECKED(Smi, line_offset, 1);
03916 bool contextual = args[2]->IsTrue();
03917 RUNTIME_ASSERT(contextual || args[2]->IsFalse());
03918
03919
03920 Handle<Context> context;
03921 if (contextual) {
03922
03923
03924
03925 Object* eval_context = EvalContext();
03926 if (eval_context->IsFailure()) return eval_context;
03927 context = Handle<Context>(Context::cast(eval_context));
03928 } else {
03929 context = Handle<Context>(Top::context()->global_context());
03930 }
03931
03932
03933
03934 bool is_global = context->IsGlobalContext();
03935 Handle<JSFunction> boilerplate =
03936 Compiler::CompileEval(source, line_offset->value(), is_global);
03937 if (boilerplate.is_null()) return Failure::Exception();
03938 Handle<JSFunction> fun =
03939 Factory::NewFunctionFromBoilerplate(boilerplate, context);
03940 return *fun;
03941 }
03942
03943
03944 static Object* Runtime_CompileScript(Arguments args) {
03945 HandleScope scope;
03946 ASSERT(args.length() == 4);
03947
03948 CONVERT_ARG_CHECKED(String, source, 0);
03949 CONVERT_ARG_CHECKED(String, script, 1);
03950 CONVERT_CHECKED(Smi, line_attrs, args[2]);
03951 int line = line_attrs->value();
03952 CONVERT_CHECKED(Smi, col_attrs, args[3]);
03953 int col = col_attrs->value();
03954 Handle<JSFunction> boilerplate =
03955 Compiler::Compile(source, script, line, col, NULL, NULL);
03956 if (boilerplate.is_null()) return Failure::Exception();
03957 Handle<JSFunction> fun =
03958 Factory::NewFunctionFromBoilerplate(boilerplate,
03959 Handle<Context>(Top::context()));
03960 return *fun;
03961 }
03962
03963
03964 static Object* Runtime_SetNewFunctionAttributes(Arguments args) {
03965
03966
03967
03968
03969 HandleScope scope;
03970 ASSERT(args.length() == 1);
03971 CONVERT_ARG_CHECKED(JSFunction, func, 0);
03972 ASSERT(func->map()->instance_type() ==
03973 Top::function_instance_map()->instance_type());
03974 ASSERT(func->map()->instance_size() ==
03975 Top::function_instance_map()->instance_size());
03976 func->set_map(*Top::function_instance_map());
03977 return *func;
03978 }
03979
03980
03981
03982
03983
03984 static Object* Runtime_PushIfAbsent(Arguments args) {
03985 ASSERT(args.length() == 2);
03986 CONVERT_CHECKED(JSArray, array, args[0]);
03987 CONVERT_CHECKED(JSArray, element, args[1]);
03988 RUNTIME_ASSERT(array->HasFastElements());
03989 int length = Smi::cast(array->length())->value();
03990 FixedArray* elements = FixedArray::cast(array->elements());
03991 for (int i = 0; i < length; i++) {
03992 if (elements->get(i) == element) return Heap::false_value();
03993 }
03994 Object* obj = array->SetFastElement(length, element);
03995 if (obj->IsFailure()) return obj;
03996 return Heap::true_value();
03997 }
03998
03999
04011 class ArrayConcatVisitor {
04012 public:
04013 ArrayConcatVisitor(Handle<FixedArray> storage,
04014 uint32_t index_limit,
04015 bool fast_elements) :
04016 storage_(storage), index_limit_(index_limit),
04017 fast_elements_(fast_elements), index_offset_(0) { }
04018
04019 void visit(uint32_t i, Handle<Object> elm) {
04020 uint32_t index = i + index_offset_;
04021 if (index >= index_limit_) return;
04022
04023 if (fast_elements_) {
04024 ASSERT(index < static_cast<uint32_t>(storage_->length()));
04025 storage_->set(index, *elm);
04026
04027 } else {
04028 Handle<Dictionary> dict = Handle<Dictionary>::cast(storage_);
04029 Handle<Dictionary> result =
04030 Factory::DictionaryAtNumberPut(dict, index, elm);
04031 if (!result.is_identical_to(dict))
04032 storage_ = result;
04033 }
04034 }
04035
04036 void increase_index_offset(uint32_t delta) {
04037 index_offset_ += delta;
04038 }
04039
04040 private:
04041 Handle<FixedArray> storage_;
04042 uint32_t index_limit_;
04043 bool fast_elements_;
04044 uint32_t index_offset_;
04045 };
04046
04047
04057 static uint32_t IterateElements(Handle<JSObject> receiver,
04058 uint32_t range,
04059 ArrayConcatVisitor* visitor) {
04060 uint32_t num_of_elements = 0;
04061
04062 if (receiver->HasFastElements()) {
04063 Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
04064 uint32_t len = elements->length();
04065 if (range < len) len = range;
04066
04067 for (uint32_t j = 0; j < len; j++) {
04068 Handle<Object> e(elements->get(j));
04069 if (!e->IsTheHole()) {
04070 num_of_elements++;
04071 if (visitor)
04072 visitor->visit(j, e);
04073 }
04074 }
04075
04076 } else {
04077 Handle<Dictionary> dict(receiver->element_dictionary());
04078 uint32_t capacity = dict->Capacity();
04079 for (uint32_t j = 0; j < capacity; j++) {
04080 Handle<Object> k(dict->KeyAt(j));
04081 if (dict->IsKey(*k)) {
04082 ASSERT(k->IsNumber());
04083 uint32_t index = static_cast<uint32_t>(k->Number());
04084 if (index < range) {
04085 num_of_elements++;
04086 if (visitor) {
04087 visitor->visit(index,
04088 Handle<Object>(dict->ValueAt(j)));
04089 }
04090 }
04091 }
04092 }
04093 }
04094
04095 return num_of_elements;
04096 }
04097
04098
04109 static uint32_t IterateArrayAndPrototypeElements(Handle<JSArray> array,
04110 ArrayConcatVisitor* visitor) {
04111 uint32_t range = static_cast<uint32_t>(array->length()->Number());
04112 Handle<Object> obj = array;
04113
04114 static const int kEstimatedPrototypes = 3;
04115 List< Handle<JSObject> > objects(kEstimatedPrototypes);
04116
04117
04118
04119
04120
04121
04122 while (!obj->IsNull()) {
04123 objects.Add(Handle<JSObject>::cast(obj));
04124 obj = Handle<Object>(obj->GetPrototype());
04125 }
04126
04127 uint32_t nof_elements = 0;
04128 for (int i = objects.length() - 1; i >= 0; i--) {
04129 Handle<JSObject> obj = objects[i];
04130 nof_elements +=
04131 IterateElements(Handle<JSObject>::cast(obj), range, visitor);
04132 }
04133
04134 return nof_elements;
04135 }
04136
04137
04153 static uint32_t IterateArguments(Handle<JSArray> arguments,
04154 ArrayConcatVisitor* visitor) {
04155 uint32_t visited_elements = 0;
04156 uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
04157
04158 for (uint32_t i = 0; i < num_of_args; i++) {
04159 Handle<Object> obj(arguments->GetElement(i));
04160 if (obj->IsJSArray()) {
04161 Handle<JSArray> array = Handle<JSArray>::cast(obj);
04162 uint32_t len = static_cast<uint32_t>(array->length()->Number());
04163 uint32_t nof_elements =
04164 IterateArrayAndPrototypeElements(array, visitor);
04165
04166
04167
04168 visited_elements += (nof_elements > len) ? len : nof_elements;
04169 if (visitor) visitor->increase_index_offset(len);
04170
04171 } else {
04172 if (visitor) {
04173 visitor->visit(0, obj);
04174 visitor->increase_index_offset(1);
04175 }
04176 visited_elements++;
04177 }
04178 }
04179 return visited_elements;
04180 }
04181
04182
04187 static Object* Runtime_ArrayConcat(Arguments args) {
04188 ASSERT(args.length() == 1);
04189 HandleScope handle_scope;
04190
04191 CONVERT_CHECKED(JSArray, arg_arrays, args[0]);
04192 Handle<JSArray> arguments(arg_arrays);
04193
04194
04195
04196 uint32_t result_length = 0;
04197 uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
04198
04199 { AssertNoAllocation nogc;
04200 for (uint32_t i = 0; i < num_of_args; i++) {
04201 Object* obj = arguments->GetElement(i);
04202 if (obj->IsJSArray()) {
04203 result_length +=
04204 static_cast<uint32_t>(JSArray::cast(obj)->length()->Number());
04205 } else {
04206 result_length++;
04207 }
04208 }
04209 }
04210
04211
04212 Handle<JSArray> result = Factory::NewJSArray(0);
04213
04214 uint32_t estimate_nof_elements = IterateArguments(arguments, NULL);
04215
04216
04217
04218 bool fast_case = (estimate_nof_elements * 2) >= result_length;
04219
04220 Handle<FixedArray> storage;
04221 if (fast_case) {
04222
04223
04224 storage = Factory::NewFixedArrayWithHoles(result_length);
04225
04226 } else {
04227
04228 uint32_t at_least_space_for = estimate_nof_elements +
04229 (estimate_nof_elements >> 2);
04230 storage = Handle<FixedArray>::cast(
04231 Factory::NewDictionary(at_least_space_for));
04232 }
04233
04234 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length));
04235
04236 ArrayConcatVisitor visitor(storage, result_length, fast_case);
04237
04238 IterateArguments(arguments, &visitor);
04239
04240 result->set_length(*len);
04241 result->set_elements(*storage);
04242
04243 return *result;
04244 }
04245
04246
04247
04248
04249 static Object* Runtime_GlobalPrint(Arguments args) {
04250 NoHandleAllocation ha;
04251 ASSERT(args.length() == 1);
04252
04253 CONVERT_CHECKED(String, string, args[0]);
04254 StringInputBuffer buffer(string);
04255 while (buffer.has_more()) {
04256 uint16_t character = buffer.GetNext();
04257 PrintF("%c", character);
04258 }
04259 return string;
04260 }
04261
04262
04263 static Object* Runtime_RemoveArrayHoles(Arguments args) {
04264 ASSERT(args.length() == 1);
04265
04266 if (!args[0]->IsJSArray()) return args[0];
04267 return JSArray::cast(args[0])->RemoveHoles();
04268 }
04269
04270
04271
04272 static Object* Runtime_MoveArrayContents(Arguments args) {
04273 ASSERT(args.length() == 2);
04274 CONVERT_CHECKED(JSArray, from, args[0]);
04275 CONVERT_CHECKED(JSArray, to, args[1]);
04276 to->SetContent(FixedArray::cast(from->elements()));
04277 to->set_length(from->length());
04278 from->SetContent(Heap::empty_fixed_array());
04279 from->set_length(0);
04280 return to;
04281 }
04282
04283
04284
04285 static Object* Runtime_EstimateNumberOfElements(Arguments args) {
04286 ASSERT(args.length() == 1);
04287 CONVERT_CHECKED(JSArray, array, args[0]);
04288 HeapObject* elements = array->elements();
04289 if (elements->IsDictionary()) {
04290 return Smi::FromInt(Dictionary::cast(elements)->NumberOfElements());
04291 } else {
04292 return array->length();
04293 }
04294 }
04295
04296
04297
04298
04299
04300 static Object* Runtime_GetArrayKeys(Arguments args) {
04301 ASSERT(args.length() == 2);
04302 HandleScope scope;
04303 CONVERT_CHECKED(JSArray, raw_array, args[0]);
04304 Handle<JSArray> array(raw_array);
04305 CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
04306 if (array->elements()->IsDictionary()) {
04307
04308
04309 Handle<FixedArray> keys = GetKeysInFixedArrayFor(array);
04310 int keys_length = keys->length();
04311 for (int i = 0; i < keys_length; i++) {
04312 Object* key = keys->get(i);
04313 uint32_t index;
04314 if (!Array::IndexFromObject(key, &index) || index >= length) {
04315
04316 keys->set_undefined(i);
04317 }
04318 }
04319 return *Factory::NewJSArrayWithElements(keys);
04320 } else {
04321 Handle<FixedArray> single_interval = Factory::NewFixedArray(2);
04322
04323 single_interval->set(0,
04324 Smi::FromInt(-1),
04325 SKIP_WRITE_BARRIER);
04326 Handle<Object> length_object =
04327 Factory::NewNumber(static_cast<double>(length));
04328 single_interval->set(1, *length_object);
04329 return *Factory::NewJSArrayWithElements(single_interval);
04330 }
04331 }
04332
04333
04334
04335
04336
04337
04338
04339 static Object* Runtime_DefineAccessor(Arguments args) {
04340 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
04341
04342 PropertyAttributes attributes = NONE;
04343 if (args.length() == 5) {
04344 CONVERT_CHECKED(Smi, attrs, args[4]);
04345 int value = attrs->value();
04346
04347 ASSERT((value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
04348 attributes = static_cast<PropertyAttributes>(value);
04349 }
04350
04351 CONVERT_CHECKED(JSObject, obj, args[0]);
04352 CONVERT_CHECKED(String, name, args[1]);
04353 CONVERT_CHECKED(Smi, flag, args[2]);
04354 CONVERT_CHECKED(JSFunction, fun, args[3]);
04355 return obj->DefineAccessor(name, flag->value() == 0, fun, attributes);
04356 }
04357
04358
04359 static Object* Runtime_LookupAccessor(Arguments args) {
04360 ASSERT(args.length() == 3);
04361 CONVERT_CHECKED(JSObject, obj, args[0]);
04362 CONVERT_CHECKED(String, name, args[1]);
04363 CONVERT_CHECKED(Smi, flag, args[2]);
04364 return obj->LookupAccessor(name, flag->value() == 0);
04365 }
04366
04367
04368
04369 static Smi* WrapFrameId(StackFrame::Id id) {
04370 ASSERT(IsAligned(OffsetFrom(id), 4));
04371 return Smi::FromInt(id >> 2);
04372 }
04373
04374
04375 static StackFrame::Id UnwrapFrameId(Smi* wrapped) {
04376 return static_cast<StackFrame::Id>(wrapped->value() << 2);
04377 }
04378
04379
04380
04381
04382
04383 static Object* Runtime_AddDebugEventListener(Arguments args) {
04384 ASSERT(args.length() == 2);
04385
04386
04387 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
04388 v8::Handle<v8::Function> fun(ToApi<v8::Function>(raw_fun));
04389 v8::Handle<v8::Value> data(ToApi<v8::Value>(args.at<Object>(0)));
04390 v8::Debug::AddDebugEventListener(fun, data);
04391
04392 return Heap::undefined_value();
04393 }
04394
04395
04396
04397
04398 static Object* Runtime_RemoveDebugEventListener(Arguments args) {
04399 ASSERT(args.length() == 1);
04400
04401
04402 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
04403 v8::Handle<v8::Function> fun(ToApi<v8::Function>(raw_fun));
04404 v8::Debug::RemoveDebugEventListener(fun);
04405
04406 return Heap::undefined_value();
04407 }
04408
04409
04410 static Object* Runtime_Break(Arguments args) {
04411 ASSERT(args.length() == 0);
04412 StackGuard::DebugBreak();
04413 return Heap::undefined_value();
04414 }
04415
04416
04417 static Object* DebugLookupResultValue(LookupResult* result) {
04418 Object* value;
04419 switch (result->type()) {
04420 case NORMAL: {
04421 Dictionary* dict =
04422 JSObject::cast(result->holder())->property_dictionary();
04423 value = dict->ValueAt(result->GetDictionaryEntry());
04424 if (value->IsTheHole()) {
04425 return Heap::undefined_value();
04426 }
04427 return value;
04428 }
04429 case FIELD:
04430 value =
04431 JSObject::cast(
04432 result->holder())->FastPropertyAt(result->GetFieldIndex());
04433 if (value->IsTheHole()) {
04434 return Heap::undefined_value();
04435 }
04436 return value;
04437 case CONSTANT_FUNCTION:
04438 return result->GetConstantFunction();
04439 case CALLBACKS:
04440 case INTERCEPTOR:
04441 case MAP_TRANSITION:
04442 case CONSTANT_TRANSITION:
04443 case NULL_DESCRIPTOR:
04444 return Heap::undefined_value();
04445 default:
04446 UNREACHABLE();
04447 }
04448 UNREACHABLE();
04449 return Heap::undefined_value();
04450 }
04451
04452
04453 static Object* Runtime_DebugGetPropertyDetails(Arguments args) {
04454 HandleScope scope;
04455
04456 ASSERT(args.length() == 2);
04457
04458 CONVERT_ARG_CHECKED(JSObject, obj, 0);
04459 CONVERT_ARG_CHECKED(String, name, 1);
04460
04461
04462
04463 uint32_t index;
04464 if (name->AsArrayIndex(&index)) {
04465 Handle<FixedArray> details = Factory::NewFixedArray(2);
04466 details->set(0, Runtime::GetElementOrCharAt(obj, index));
04467 details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
04468 return *Factory::NewJSArrayWithElements(details);
04469 }
04470
04471
04472 LookupResult result;
04473 obj->Lookup(*name, &result);
04474 if (result.IsProperty()) {
04475 Handle<Object> value(DebugLookupResultValue(&result));
04476 Handle<FixedArray> details = Factory::NewFixedArray(2);
04477 details->set(0, *value);
04478 details->set(1, result.GetPropertyDetails().AsSmi());
04479 return *Factory::NewJSArrayWithElements(details);
04480 }
04481 return Heap::undefined_value();
04482 }
04483
04484
04485 static Object* Runtime_DebugGetProperty(Arguments args) {
04486 HandleScope scope;
04487
04488 ASSERT(args.length() == 2);
04489
04490 CONVERT_ARG_CHECKED(JSObject, obj, 0);
04491 CONVERT_ARG_CHECKED(String, name, 1);
04492
04493 LookupResult result;
04494 obj->Lookup(*name, &result);
04495 if (result.IsProperty()) {
04496 return DebugLookupResultValue(&result);
04497 }
04498 return Heap::undefined_value();
04499 }
04500
04501
04502
04503
04504 static Object* Runtime_DebugLocalPropertyNames(Arguments args) {
04505 HandleScope scope;
04506 ASSERT(args.length() == 1);
04507 if (!args[0]->IsJSObject()) {
04508 return Heap::undefined_value();
04509 }
04510 CONVERT_ARG_CHECKED(JSObject, obj, 0);
04511
04512 int n = obj->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
04513 Handle<FixedArray> names = Factory::NewFixedArray(n);
04514 obj->GetLocalPropertyNames(*names);
04515 return *Factory::NewJSArrayWithElements(names);
04516 }
04517
04518
04519
04520
04521 static Object* Runtime_DebugLocalElementNames(Arguments args) {
04522 HandleScope scope;
04523 ASSERT(args.length() == 1);
04524 if (!args[0]->IsJSObject()) {
04525 return Heap::undefined_value();
04526 }
04527 CONVERT_ARG_CHECKED(JSObject, obj, 0);
04528
04529 int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
04530 Handle<FixedArray> names = Factory::NewFixedArray(n);
04531 obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
04532 return *Factory::NewJSArrayWithElements(names);
04533 }
04534
04535
04536
04537
04538 static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) {
04539 ASSERT(args.length() == 1);
04540 CONVERT_CHECKED(Smi, details, args[0]);
04541 PropertyType type = PropertyDetails(details).type();
04542 return Smi::FromInt(static_cast<int>(type));
04543 }
04544
04545
04546
04547
04548 static Object* Runtime_DebugPropertyAttributesFromDetails(Arguments args) {
04549 ASSERT(args.length() == 1);
04550 CONVERT_CHECKED(Smi, details, args[0]);
04551 PropertyAttributes attributes = PropertyDetails(details).attributes();
04552 return Smi::FromInt(static_cast<int>(attributes));
04553 }
04554
04555
04556
04557
04558 static Object* Runtime_DebugPropertyIndexFromDetails(Arguments args) {
04559 ASSERT(args.length() == 1);
04560 CONVERT_CHECKED(Smi, details, args[0]);
04561 int index = PropertyDetails(details).index();
04562 return Smi::FromInt(index);
04563 }
04564
04565
04566
04567
04568 static Object* Runtime_DebugInterceptorInfo(Arguments args) {
04569 HandleScope scope;
04570 ASSERT(args.length() == 1);
04571 if (!args[0]->IsJSObject()) {
04572 return Smi::FromInt(0);
04573 }
04574 CONVERT_ARG_CHECKED(JSObject, obj, 0);
04575
04576 int result = 0;
04577 if (obj->HasNamedInterceptor()) result |= 2;
04578 if (obj->HasIndexedInterceptor()) result |= 1;
04579
04580 return Smi::FromInt(result);
04581 }
04582
04583
04584
04585
04586 static Object* Runtime_DebugNamedInterceptorPropertyNames(Arguments args) {
04587 HandleScope scope;
04588 ASSERT(args.length() == 1);
04589 CONVERT_ARG_CHECKED(JSObject, obj, 0);
04590 RUNTIME_ASSERT(obj->HasNamedInterceptor());
04591
04592 v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
04593 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
04594 return Heap::undefined_value();
04595 }
04596
04597
04598
04599
04600 static Object* Runtime_DebugIndexedInterceptorElementNames(Arguments args) {
04601 HandleScope scope;
04602 ASSERT(args.length() == 1);
04603 CONVERT_ARG_CHECKED(JSObject, obj, 0);
04604 RUNTIME_ASSERT(obj->HasIndexedInterceptor());
04605
04606 v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
04607 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
04608 return Heap::undefined_value();
04609 }
04610
04611
04612
04613
04614
04615 static Object* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) {
04616 HandleScope scope;
04617 ASSERT(args.length() == 2);
04618 CONVERT_ARG_CHECKED(JSObject, obj, 0);
04619 RUNTIME_ASSERT(obj->HasNamedInterceptor());
04620 CONVERT_ARG_CHECKED(String, name, 1);
04621
04622 PropertyAttributes attributes;
04623 return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
04624 }
04625
04626
04627
04628
04629
04630 static Object* Runtime_DebugIndexedInterceptorElementValue(Arguments args) {
04631 HandleScope scope;
04632 ASSERT(args.length() == 2);
04633 CONVERT_ARG_CHECKED(JSObject, obj, 0);
04634 RUNTIME_ASSERT(obj->HasIndexedInterceptor());
04635 CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
04636
04637 return obj->GetElementWithInterceptor(*obj, index);
04638 }
04639
04640
04641 static Object* Runtime_CheckExecutionState(Arguments args) {
04642 ASSERT(args.length() >= 1);
04643 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
04644
04645
04646 if (break_id != Top::break_id() ||
04647 Top::break_frame_id() == StackFrame::NO_ID) {
04648 return Top::Throw(Heap::illegal_execution_state_symbol());
04649 }
04650
04651 return Heap::true_value();
04652 }
04653
04654
04655 static Object* Runtime_GetFrameCount(Arguments args) {
04656 HandleScope scope;
04657 ASSERT(args.length() == 1);
04658
04659
04660 Object* result = Runtime_CheckExecutionState(args);
04661 if (result->IsFailure()) return result;
04662
04663
04664 int n = 0;
04665 StackFrame::Id id = Top::break_frame_id();
04666 for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) n++;
04667 return Smi::FromInt(n);
04668 }
04669
04670
04671 static const int kFrameDetailsFrameIdIndex = 0;
04672 static const int kFrameDetailsReceiverIndex = 1;
04673 static const int kFrameDetailsFunctionIndex = 2;
04674 static const int kFrameDetailsArgumentCountIndex = 3;
04675 static const int kFrameDetailsLocalCountIndex = 4;
04676 static const int kFrameDetailsSourcePositionIndex = 5;
04677 static const int kFrameDetailsConstructCallIndex = 6;
04678 static const int kFrameDetailsDebuggerFrameIndex = 7;
04679 static const int kFrameDetailsFirstDynamicIndex = 8;
04680
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690
04691
04692
04693
04694
04695
04696 static Object* Runtime_GetFrameDetails(Arguments args) {
04697 HandleScope scope;
04698 ASSERT(args.length() == 2);
04699
04700
04701 Object* check = Runtime_CheckExecutionState(args);
04702 if (check->IsFailure()) return check;
04703 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
04704
04705
04706 StackFrame::Id id = Top::break_frame_id();
04707 int count = 0;
04708 JavaScriptFrameIterator it(id);
04709 for (; !it.done(); it.Advance()) {
04710 if (count == index) break;
04711 count++;
04712 }
04713 if (it.done()) return Heap::undefined_value();
04714
04715
04716
04717 SaveContext* save = Top::save_context();
04718 while (save != NULL && reinterpret_cast<Address>(save) < it.frame()->sp()) {
04719 save = save->prev();
04720 }
04721
04722
04723 Handle<Object> frame_id(WrapFrameId(it.frame()->id()));
04724
04725
04726 int position = it.frame()->FindCode()->SourcePosition(it.frame()->pc());
04727
04728
04729 bool constructor = it.frame()->IsConstructor();
04730
04731
04732 Handle<Code> code(it.frame()->FindCode());
04733 ScopeInfo<> info(*code);
04734
04735
04736 Handle<Context> context(Context::cast(it.frame()->context()));
04737
04738
04739
04740
04741
04742
04743 Handle<FixedArray> locals = Factory::NewFixedArray(info.NumberOfLocals() * 2);
04744 for (int i = 0; i < info.NumberOfLocals(); i++) {
04745
04746 locals->set(i * 2, *info.LocalName(i));
04747
04748
04749
04750 if (i < info.number_of_stack_slots()) {
04751 locals->set(i * 2 + 1, it.frame()->GetExpression(i));
04752 } else {
04753 Handle<String> name = info.LocalName(i);
04754
04755
04756 while (!context->is_function_context()) {
04757 context = Handle<Context>(context->previous());
04758 }
04759 ASSERT(context->is_function_context());
04760 locals->set(i * 2 + 1,
04761 context->get(ScopeInfo<>::ContextSlotIndex(*code, *name,
04762 NULL)));
04763 }
04764 }
04765
04766
04767
04768
04769
04770
04771
04772
04773 it.AdvanceToArgumentsFrame();
04774
04775
04776
04777 int argument_count = info.number_of_parameters();
04778 if (argument_count < it.frame()->GetProvidedParametersCount()) {
04779 argument_count = it.frame()->GetProvidedParametersCount();
04780 }
04781
04782
04783 int details_size = kFrameDetailsFirstDynamicIndex +
04784 2 * (argument_count + info.NumberOfLocals());
04785 Handle<FixedArray> details = Factory::NewFixedArray(details_size);
04786
04787
04788 details->set(kFrameDetailsFrameIdIndex, *frame_id);
04789
04790
04791 details->set(kFrameDetailsFunctionIndex, it.frame()->function());
04792
04793
04794 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
04795
04796
04797 details->set(kFrameDetailsLocalCountIndex,
04798 Smi::FromInt(info.NumberOfLocals()));
04799
04800
04801 if (position != RelocInfo::kNoPosition) {
04802 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
04803 } else {
04804 details->set(kFrameDetailsSourcePositionIndex, Heap::undefined_value());
04805 }
04806
04807
04808 details->set(kFrameDetailsConstructCallIndex, Heap::ToBoolean(constructor));
04809
04810
04811 details->set(kFrameDetailsDebuggerFrameIndex,
04812 Heap::ToBoolean(*save->context() == *Debug::debug_context()));
04813
04814
04815 int details_index = kFrameDetailsFirstDynamicIndex;
04816
04817
04818 for (int i = 0; i < argument_count; i++) {
04819
04820 if (i < info.number_of_parameters()) {
04821 details->set(details_index++, *info.parameter_name(i));
04822 } else {
04823 details->set(details_index++, Heap::undefined_value());
04824 }
04825
04826
04827 if (i < it.frame()->GetProvidedParametersCount()) {
04828 details->set(details_index++, it.frame()->GetParameter(i));
04829 } else {
04830 details->set(details_index++, Heap::undefined_value());
04831 }
04832 }
04833
04834
04835 for (int i = 0; i < info.NumberOfLocals() * 2; i++) {
04836 details->set(details_index++, locals->get(i));
04837 }
04838
04839
04840
04841
04842 Handle<Object> receiver(it.frame()->receiver());
04843 if (!receiver->IsJSObject()) {
04844
04845
04846
04847
04848
04849 it.Advance();
04850 Handle<Context> calling_frames_global_context(
04851 Context::cast(Context::cast(it.frame()->context())->global_context()));
04852 receiver = Factory::ToObject(receiver, calling_frames_global_context);
04853 }
04854 details->set(kFrameDetailsReceiverIndex, *receiver);
04855
04856 ASSERT_EQ(details_size, details_index);
04857 return *Factory::NewJSArrayWithElements(details);
04858 }
04859
04860
04861 static Object* Runtime_GetCFrames(Arguments args) {
04862 HandleScope scope;
04863 ASSERT(args.length() == 1);
04864 Object* result = Runtime_CheckExecutionState(args);
04865 if (result->IsFailure()) return result;
04866
04867 static const int kMaxCFramesSize = 200;
04868 OS::StackFrame frames[kMaxCFramesSize];
04869 int frames_count = OS::StackWalk(frames, kMaxCFramesSize);
04870 if (frames_count == OS::kStackWalkError) {
04871 return Heap::undefined_value();
04872 }
04873
04874 Handle<String> address_str = Factory::LookupAsciiSymbol("address");
04875 Handle<String> text_str = Factory::LookupAsciiSymbol("text");
04876 Handle<FixedArray> frames_array = Factory::NewFixedArray(frames_count);
04877 for (int i = 0; i < frames_count; i++) {
04878 Handle<JSObject> frame_value = Factory::NewJSObject(Top::object_function());
04879 frame_value->SetProperty(
04880 *address_str,
04881 *Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address)),
04882 NONE);
04883
04884
04885 Handle<String> frame_text;
04886 if (strlen(frames[i].text) > 0) {
04887 Vector<const char> str(frames[i].text, strlen(frames[i].text));
04888 frame_text = Factory::NewStringFromAscii(str);
04889 }
04890
04891 if (!frame_text.is_null()) {
04892 frame_value->SetProperty(*text_str, *frame_text, NONE);
04893 }
04894
04895 frames_array->set(i, *frame_value);
04896 }
04897 return *Factory::NewJSArrayWithElements(frames_array);
04898 }
04899
04900
04901 static Object* Runtime_GetBreakLocations(Arguments args) {
04902 HandleScope scope;
04903 ASSERT(args.length() == 1);
04904
04905 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
04906 Handle<SharedFunctionInfo> shared(raw_fun->shared());
04907
04908 Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
04909 if (break_locations->IsUndefined()) return Heap::undefined_value();
04910
04911 return *Factory::NewJSArrayWithElements(
04912 Handle<FixedArray>::cast(break_locations));
04913 }
04914
04915
04916
04917
04918
04919
04920 static Object* Runtime_SetFunctionBreakPoint(Arguments args) {
04921 HandleScope scope;
04922 ASSERT(args.length() == 3);
04923 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
04924 Handle<SharedFunctionInfo> shared(raw_fun->shared());
04925 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
04926 RUNTIME_ASSERT(source_position >= 0);
04927 Handle<Object> break_point_object_arg = args.at<Object>(2);
04928
04929
04930 Debug::SetBreakPoint(shared, source_position, break_point_object_arg);
04931
04932 return Heap::undefined_value();
04933 }
04934
04935
04936 static Object* FindSharedFunctionInfoInScript(Handle<Script> script,
04937 int position) {
04938
04939
04940
04941
04942
04943
04944
04945
04946 bool done = false;
04947
04948 int target_start_position = RelocInfo::kNoPosition;
04949 Handle<SharedFunctionInfo> target;
04950
04951 Handle<SharedFunctionInfo> last;
04952 while (!done) {
04953 HeapIterator iterator;
04954 while (iterator.has_next()) {
04955 HeapObject* obj = iterator.next();
04956 ASSERT(obj != NULL);
04957 if (obj->IsSharedFunctionInfo()) {
04958 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
04959 if (shared->script() == *script) {
04960
04961
04962 int start_position = shared->function_token_position();
04963 if (start_position == RelocInfo::kNoPosition) {
04964 start_position = shared->start_position();
04965 }
04966 if (start_position <= position &&
04967 position <= shared->end_position()) {
04968
04969
04970 if (target.is_null()) {
04971 target_start_position = start_position;
04972 target = shared;
04973 } else {
04974 if (target_start_position < start_position &&
04975 shared->end_position() < target->end_position()) {
04976 target_start_position = start_position;
04977 target = shared;
04978 }
04979 }
04980 }
04981
04982
04983 if (last.is_null() ||
04984 shared->end_position() > last->start_position()) {
04985 last = shared;
04986 }
04987 }
04988 }
04989 }
04990
04991
04992 if (target.is_null()) {
04993 if (!last.is_null()) {
04994
04995 target = last;
04996 } else {
04997
04998 return Heap::undefined_value();
04999 }
05000 }
05001
05002
05003
05004
05005 done = target->is_compiled();
05006 if (!done) {
05007
05008
05009 CompileLazyShared(target, KEEP_EXCEPTION);
05010 }
05011 }
05012
05013 return *target;
05014 }
05015
05016
05017
05018
05019
05020
05021
05022 static Object* Runtime_SetScriptBreakPoint(Arguments args) {
05023 HandleScope scope;
05024 ASSERT(args.length() == 3);
05025 CONVERT_ARG_CHECKED(JSValue, wrapper, 0);
05026 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
05027 RUNTIME_ASSERT(source_position >= 0);
05028 Handle<Object> break_point_object_arg = args.at<Object>(2);
05029
05030
05031 RUNTIME_ASSERT(wrapper->value()->IsScript());
05032 Handle<Script> script(Script::cast(wrapper->value()));
05033
05034 Object* result = FindSharedFunctionInfoInScript(script, source_position);
05035 if (!result->IsUndefined()) {
05036 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
05037
05038
05039 int position;
05040 if (shared->start_position() > source_position) {
05041 position = 0;
05042 } else {
05043 position = source_position - shared->start_position();
05044 }
05045 Debug::SetBreakPoint(shared, position, break_point_object_arg);
05046 }
05047 return Heap::undefined_value();
05048 }
05049
05050
05051
05052
05053 static Object* Runtime_ClearBreakPoint(Arguments args) {
05054 HandleScope scope;
05055 ASSERT(args.length() == 1);
05056 Handle<Object> break_point_object_arg = args.at<Object>(0);
05057
05058
05059 Debug::ClearBreakPoint(break_point_object_arg);
05060
05061 return Heap::undefined_value();
05062 }
05063
05064
05065
05066
05067
05068 static Object* Runtime_ChangeBreakOnException(Arguments args) {
05069 HandleScope scope;
05070 ASSERT(args.length() == 2);
05071 ASSERT(args[0]->IsNumber());
05072 ASSERT(args[1]->IsBoolean());
05073
05074
05075 ExceptionBreakType type =
05076 static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
05077 bool enable = args[1]->ToBoolean()->IsTrue();
05078 Debug::ChangeBreakOnException(type, enable);
05079 return Heap::undefined_value();
05080 }
05081
05082
05083
05084
05085
05086
05087 static Object* Runtime_PrepareStep(Arguments args) {
05088 HandleScope scope;
05089 ASSERT(args.length() == 3);
05090
05091 Object* check = Runtime_CheckExecutionState(args);
05092 if (check->IsFailure()) return check;
05093 if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
05094 return Top::Throw(Heap::illegal_argument_symbol());
05095 }
05096
05097
05098 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
05099 if (step_action != StepIn &&
05100 step_action != StepNext &&
05101 step_action != StepOut &&
05102 step_action != StepInMin &&
05103 step_action != StepMin) {
05104 return Top::Throw(Heap::illegal_argument_symbol());
05105 }
05106
05107
05108 int step_count = NumberToInt32(args[2]);
05109 if (step_count < 1) {
05110 return Top::Throw(Heap::illegal_argument_symbol());
05111 }
05112
05113
05114 Debug::PrepareStep(static_cast<StepAction>(step_action), step_count);
05115 return Heap::undefined_value();
05116 }
05117
05118
05119
05120 static Object* Runtime_ClearStepping(Arguments args) {
05121 HandleScope scope;
05122 ASSERT(args.length() == 0);
05123 Debug::ClearStepping();
05124 return Heap::undefined_value();
05125 }
05126
05127
05128
05129
05130 static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
05131 Handle<Context> function_context) {
05132
05133 if (context_chain->is_function_context()) {
05134 return function_context;
05135 }
05136
05137
05138 Handle<Context> previous(context_chain->previous());
05139 Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
05140 return Factory::NewWithContext(
05141 CopyWithContextChain(function_context, previous), extension);
05142 }
05143
05144
05145
05146
05147 static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
05148 Handle<JSFunction> function,
05149 Handle<Code> code,
05150 const ScopeInfo<>* sinfo,
05151 Handle<Context> function_context) {
05152
05153
05154
05155 int index;
05156 if (sinfo->number_of_stack_slots() > 0) {
05157 index = ScopeInfo<>::StackSlotIndex(*code, Heap::arguments_symbol());
05158 if (index != -1) {
05159 return Handle<Object>(frame->GetExpression(index));
05160 }
05161 }
05162
05163 if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
05164 index = ScopeInfo<>::ContextSlotIndex(*code, Heap::arguments_symbol(),
05165 NULL);
05166 if (index != -1) {
05167 return Handle<Object>(function_context->get(index));
05168 }
05169 }
05170
05171 const int length = frame->GetProvidedParametersCount();
05172 Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
05173 Handle<FixedArray> array = Factory::NewFixedArray(length);
05174 WriteBarrierMode mode = array->GetWriteBarrierMode();
05175 for (int i = 0; i < length; i++) {
05176 array->set(i, frame->GetParameter(i), mode);
05177 }
05178 arguments->set_elements(*array);
05179 return arguments;
05180 }
05181
05182
05183
05184
05185
05186
05187
05188
05189
05190
05191
05192
05193
05194 static Object* Runtime_DebugEvaluate(Arguments args) {
05195 HandleScope scope;
05196
05197
05198
05199 ASSERT(args.length() == 4);
05200 Object* check_result = Runtime_CheckExecutionState(args);
05201 if (check_result->IsFailure()) return check_result;
05202 CONVERT_CHECKED(Smi, wrapped_id, args[1]);
05203 CONVERT_ARG_CHECKED(String, source, 2);
05204 CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
05205
05206
05207 DisableBreak disable_break_save(disable_break);
05208
05209
05210 StackFrame::Id id = UnwrapFrameId(wrapped_id);
05211 JavaScriptFrameIterator it(id);
05212 JavaScriptFrame* frame = it.frame();
05213 Handle<JSFunction> function(JSFunction::cast(frame->function()));
05214 Handle<Code> code(function->code());
05215 ScopeInfo<> sinfo(*code);
05216
05217
05218
05219 SaveContext* save = Top::save_context();
05220 while (save != NULL && reinterpret_cast<Address>(save) < frame->sp()) {
05221 save = save->prev();
05222 }
05223 ASSERT(save != NULL);
05224 SaveContext savex;
05225 Top::set_context(*(save->context()));
05226
05227
05228
05229
05230
05231
05232
05233 Handle<JSFunction> go_between =
05234 Factory::NewFunction(Factory::empty_string(), Factory::undefined_value());
05235 go_between->set_context(function->context());
05236 #ifdef DEBUG
05237 ScopeInfo<> go_between_sinfo(go_between->shared()->code());
05238 ASSERT(go_between_sinfo.number_of_parameters() == 0);
05239 ASSERT(go_between_sinfo.number_of_context_slots() == 0);
05240 #endif
05241
05242
05243
05244
05245 Handle<JSObject> context_ext = Factory::NewJSObject(Top::object_function());
05246
05247 for (int i = 0; i < sinfo.number_of_parameters(); ++i) {
05248 SetProperty(context_ext,
05249 sinfo.parameter_name(i),
05250 Handle<Object>(frame->GetParameter(i)), NONE);
05251 }
05252
05253 for (int i = 0; i < sinfo.number_of_stack_slots(); i++) {
05254 SetProperty(context_ext,
05255 sinfo.stack_slot_name(i),
05256 Handle<Object>(frame->GetExpression(i)), NONE);
05257 }
05258
05259 Handle<Context> frame_context(Context::cast(frame->context()));
05260 Handle<Context> function_context(frame_context->fcontext());
05261 for (int i = Context::MIN_CONTEXT_SLOTS;
05262 i < sinfo.number_of_context_slots();
05263 ++i) {
05264 int context_index =
05265 ScopeInfo<>::ContextSlotIndex(*code, *sinfo.context_slot_name(i), NULL);
05266 SetProperty(context_ext,
05267 sinfo.context_slot_name(i),
05268 Handle<Object>(function_context->get(context_index)), NONE);
05269 }
05270
05271
05272 if (function_context->has_extension() &&
05273 !function_context->IsGlobalContext()) {
05274 Handle<JSObject> ext(JSObject::cast(function_context->extension()));
05275 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
05276 for (int i = 0; i < keys->length(); i++) {
05277
05278 ASSERT(keys->get(i)->IsString());
05279 Handle<String> key(String::cast(keys->get(i)));
05280 SetProperty(context_ext, key, GetProperty(ext, key), NONE);
05281 }
05282 }
05283
05284
05285
05286 Handle<Context> context =
05287 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between);
05288 context->set_extension(*context_ext);
05289
05290 context = CopyWithContextChain(frame_context, context);
05291
05292
05293
05294
05295
05296
05297 static const char* source_str =
05298 "function(arguments,__source__){return eval(__source__);}";
05299 static const int source_str_length = strlen(source_str);
05300 Handle<String> function_source =
05301 Factory::NewStringFromAscii(Vector<const char>(source_str,
05302 source_str_length));
05303 Handle<JSFunction> boilerplate =
05304 Compiler::CompileEval(function_source, 0, context->IsGlobalContext());
05305 if (boilerplate.is_null()) return Failure::Exception();
05306 Handle<JSFunction> compiled_function =
05307 Factory::NewFunctionFromBoilerplate(boilerplate, context);
05308
05309
05310 bool has_pending_exception;
05311 Handle<Object> receiver(frame->receiver());
05312 Handle<Object> evaluation_function =
05313 Execution::Call(compiled_function, receiver, 0, NULL,
05314 &has_pending_exception);
05315
05316 Handle<Object> arguments = GetArgumentsObject(frame, function, code, &sinfo,
05317 function_context);
05318
05319
05320 const int argc = 2;
05321 Object** argv[argc] = { arguments.location(),
05322 Handle<Object>::cast(source).location() };
05323 Handle<Object> result =
05324 Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver,
05325 argc, argv, &has_pending_exception);
05326 return *result;
05327 }
05328
05329
05330 static Object* Runtime_DebugEvaluateGlobal(Arguments args) {
05331 HandleScope scope;
05332
05333
05334
05335 ASSERT(args.length() == 3);
05336 Object* check_result = Runtime_CheckExecutionState(args);
05337 if (check_result->IsFailure()) return check_result;
05338 CONVERT_ARG_CHECKED(String, source, 1);
05339 CONVERT_BOOLEAN_CHECKED(disable_break, args[2]);
05340
05341
05342 DisableBreak disable_break_save(disable_break);
05343
05344
05345 SaveContext save;
05346 SaveContext* top = &save;
05347 while (top != NULL && *top->context() == *Debug::debug_context()) {
05348 top = top->prev();
05349 }
05350 if (top != NULL) {
05351 Top::set_context(*top->context());
05352 }
05353
05354
05355
05356 Handle<Context> context = Top::global_context();
05357
05358
05359 Handle<JSFunction> boilerplate(Compiler::CompileEval(source, 0, true));
05360 if (boilerplate.is_null()) return Failure::Exception();
05361 Handle<JSFunction> compiled_function =
05362 Handle<JSFunction>(Factory::NewFunctionFromBoilerplate(boilerplate,
05363 context));
05364
05365
05366 bool has_pending_exception;
05367 Handle<Object> receiver = Top::global();
05368 Handle<Object> result =
05369 Execution::Call(compiled_function, receiver, 0, NULL,
05370 &has_pending_exception);
05371 return *result;
05372 }
05373
05374
05375
05376 static int DebugGetLoadedScripts(FixedArray* instances, int instances_size) {
05377 NoHandleAllocation ha;
05378 AssertNoAllocation no_alloc;
05379
05380
05381 Context* context = Top::context()->global_context();
05382 Script* empty = context->empty_script();
05383
05384
05385 int count = 0;
05386 HeapIterator iterator;
05387 while (iterator.has_next()) {
05388 HeapObject* obj = iterator.next();
05389 ASSERT(obj != NULL);
05390 if (obj->IsScript() && obj != empty) {
05391 if (instances != NULL && count < instances_size) {
05392 instances->set(count, obj);
05393 }
05394 count++;
05395 }
05396 }
05397
05398 return count;
05399 }
05400
05401
05402 static Object* Runtime_DebugGetLoadedScripts(Arguments args) {
05403 HandleScope scope;
05404 ASSERT(args.length() == 0);
05405
05406
05407
05408
05409 Heap::CollectAllGarbage();
05410 Heap::CollectAllGarbage();
05411
05412
05413 int count;
05414 count = DebugGetLoadedScripts(NULL, 0);
05415
05416
05417 Handle<FixedArray> instances = Factory::NewFixedArray(count);
05418
05419
05420 count = DebugGetLoadedScripts(*instances, count);
05421
05422
05423 for (int i = 0; i < count; i++) {
05424 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
05425
05426
05427
05428
05429
05430 Handle<JSValue> wrapper = GetScriptWrapper(script);
05431 instances->set(i, *wrapper);
05432 }
05433
05434
05435 Handle<JSObject> result = Factory::NewJSObject(Top::array_function());
05436 Handle<JSArray>::cast(result)->SetContent(*instances);
05437 return *result;
05438 }
05439
05440
05441
05442 static int DebugReferencedBy(JSObject* target,
05443 Object* instance_filter, int max_references,
05444 FixedArray* instances, int instances_size,
05445 JSFunction* context_extension_function,
05446 JSFunction* arguments_function) {
05447 NoHandleAllocation ha;
05448 AssertNoAllocation no_alloc;
05449
05450
05451 int count = 0;
05452 JSObject* last = NULL;
05453 HeapIterator iterator;
05454 while (iterator.has_next() &&
05455 (max_references == 0 || count < max_references)) {
05456
05457 HeapObject* heap_obj = iterator.next();
05458 if (heap_obj->IsJSObject()) {
05459
05460
05461 JSObject* obj = JSObject::cast(heap_obj);
05462 if (obj->map()->constructor() == context_extension_function ||
05463 obj->map()->constructor() == arguments_function) {
05464 continue;
05465 }
05466
05467
05468 if (obj->ReferencesObject(target)) {
05469
05470
05471 if (!instance_filter->IsUndefined()) {
05472 Object* V = obj;
05473 while (true) {
05474 Object* prototype = V->GetPrototype();
05475 if (prototype->IsNull()) {
05476 break;
05477 }
05478 if (instance_filter == prototype) {
05479 obj = NULL;
05480 break;
05481 }
05482 V = prototype;
05483 }
05484 }
05485
05486 if (obj != NULL) {
05487
05488
05489 if (instances != NULL && count < instances_size) {
05490 instances->set(count, obj);
05491 }
05492 last = obj;
05493 count++;
05494 }
05495 }
05496 }
05497 }
05498
05499
05500
05501
05502
05503 if (count == 1 && last == target) {
05504 count = 0;
05505 }
05506
05507
05508 return count;
05509 }
05510
05511
05512
05513
05514
05515
05516 static Object* Runtime_DebugReferencedBy(Arguments args) {
05517 ASSERT(args.length() == 3);
05518
05519
05520 Heap::CollectAllGarbage();
05521
05522
05523 CONVERT_CHECKED(JSObject, target, args[0]);
05524 Object* instance_filter = args[1];
05525 RUNTIME_ASSERT(instance_filter->IsUndefined() ||
05526 instance_filter->IsJSObject());
05527 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
05528 RUNTIME_ASSERT(max_references >= 0);
05529
05530
05531 JSFunction* context_extension_function =
05532 Top::context()->global_context()->context_extension_function();
05533 JSObject* arguments_boilerplate =
05534 Top::context()->global_context()->arguments_boilerplate();
05535 JSFunction* arguments_function =
05536 JSFunction::cast(arguments_boilerplate->map()->constructor());
05537
05538
05539 int count;
05540 count = DebugReferencedBy(target, instance_filter, max_references,
05541 NULL, 0,
05542 context_extension_function, arguments_function);
05543
05544
05545 Object* object = Heap::AllocateFixedArray(count);
05546 if (object->IsFailure()) return object;
05547 FixedArray* instances = FixedArray::cast(object);
05548
05549
05550 count = DebugReferencedBy(target, instance_filter, max_references,
05551 instances, count,
05552 context_extension_function, arguments_function);
05553
05554
05555 Object* result =
05556 Heap::AllocateJSObject(
05557 Top::context()->global_context()->array_function());
05558 if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
05559 return result;
05560 }
05561
05562
05563
05564 static int DebugConstructedBy(JSFunction* constructor, int max_references,
05565 FixedArray* instances, int instances_size) {
05566 AssertNoAllocation no_alloc;
05567
05568
05569 int count = 0;
05570 HeapIterator iterator;
05571 while (iterator.has_next() &&
05572 (max_references == 0 || count < max_references)) {
05573
05574 HeapObject* heap_obj = iterator.next();
05575 if (heap_obj->IsJSObject()) {
05576 JSObject* obj = JSObject::cast(heap_obj);
05577 if (obj->map()->constructor() == constructor) {
05578
05579
05580 if (instances != NULL && count < instances_size) {
05581 instances->set(count, obj);
05582 }
05583 count++;
05584 }
05585 }
05586 }
05587
05588
05589 return count;
05590 }
05591
05592
05593
05594
05595
05596 static Object* Runtime_DebugConstructedBy(Arguments args) {
05597 ASSERT(args.length() == 2);
05598
05599
05600 Heap::CollectAllGarbage();
05601
05602
05603 CONVERT_CHECKED(JSFunction, constructor, args[0]);
05604 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
05605 RUNTIME_ASSERT(max_references >= 0);
05606
05607
05608 int count;
05609 count = DebugConstructedBy(constructor, max_references, NULL, 0);
05610
05611
05612 Object* object = Heap::AllocateFixedArray(count);
05613 if (object->IsFailure()) return object;
05614 FixedArray* instances = FixedArray::cast(object);
05615
05616
05617 count = DebugConstructedBy(constructor, max_references, instances, count);
05618
05619
05620 Object* result =
05621 Heap::AllocateJSObject(
05622 Top::context()->global_context()->array_function());
05623 if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
05624 return result;
05625 }
05626
05627
05628 static Object* Runtime_GetPrototype(Arguments args) {
05629 ASSERT(args.length() == 1);
05630
05631 CONVERT_CHECKED(JSObject, obj, args[0]);
05632
05633 return obj->GetPrototype();
05634 }
05635
05636
05637 static Object* Runtime_SystemBreak(Arguments args) {
05638 ASSERT(args.length() == 0);
05639 CPU::DebugBreak();
05640 return Heap::undefined_value();
05641 }
05642
05643
05644
05645
05646
05647
05648
05649
05650 static Handle<Object> Runtime_GetScriptFromScriptName(
05651 Handle<String> script_name) {
05652
05653
05654 Handle<Script> script;
05655 HeapIterator iterator;
05656 while (script.is_null() && iterator.has_next()) {
05657 HeapObject* obj = iterator.next();
05658
05659 if (obj->IsScript()) {
05660 if (Script::cast(obj)->name()->IsString()) {
05661 if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
05662 script = Handle<Script>(Script::cast(obj));
05663 }
05664 }
05665 }
05666 }
05667
05668
05669 if (script.is_null()) return Factory::undefined_value();
05670
05671
05672 return GetScriptWrapper(script);
05673 }
05674
05675
05676
05677
05678
05679 static Object* Runtime_GetScript(Arguments args) {
05680 HandleScope scope;
05681
05682 ASSERT(args.length() == 1);
05683
05684 CONVERT_CHECKED(String, script_name, args[0]);
05685
05686
05687 Handle<Object> result =
05688 Runtime_GetScriptFromScriptName(Handle<String>(script_name));
05689 return *result;
05690 }
05691
05692
05693 static Object* Runtime_FunctionGetAssemblerCode(Arguments args) {
05694 #ifdef DEBUG
05695 HandleScope scope;
05696 ASSERT(args.length() == 1);
05697
05698 CONVERT_ARG_CHECKED(JSFunction, func, 0);
05699 if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
05700 return Failure::Exception();
05701 }
05702 func->code()->PrintLn();
05703 #endif // DEBUG
05704 return Heap::undefined_value();
05705 }
05706
05707
05708 static Object* Runtime_Abort(Arguments args) {
05709 ASSERT(args.length() == 2);
05710 OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +
05711 Smi::cast(args[1])->value());
05712 Top::PrintStack();
05713 OS::Abort();
05714 UNREACHABLE();
05715 return NULL;
05716 }
05717
05718
05719 #ifdef DEBUG
05720
05721
05722 static Object* Runtime_ListNatives(Arguments args) {
05723 ASSERT(args.length() == 0);
05724 HandleScope scope;
05725 Handle<JSArray> result = Factory::NewJSArray(0);
05726 int index = 0;
05727 #define ADD_ENTRY(Name, argc) \
05728 { \
05729 HandleScope inner; \
05730 Handle<String> name = \
05731 Factory::NewStringFromAscii(Vector<const char>(#Name, strlen(#Name))); \
05732 Handle<JSArray> pair = Factory::NewJSArray(0); \
05733 SetElement(pair, 0, name); \
05734 SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc))); \
05735 SetElement(result, index++, pair); \
05736 }
05737 RUNTIME_FUNCTION_LIST(ADD_ENTRY)
05738 #undef ADD_ENTRY
05739 return *result;
05740 }
05741 #endif
05742
05743
05744 static Object* Runtime_IS_VAR(Arguments args) {
05745 UNREACHABLE();
05746 return NULL;
05747 }
05748
05749
05750
05751
05752
05753 #define F(name, nargs) \
05754 { #name, "RuntimeStub_" #name, FUNCTION_ADDR(Runtime_##name), nargs, \
05755 static_cast<int>(Runtime::k##name) },
05756
05757 static Runtime::Function Runtime_functions[] = {
05758 RUNTIME_FUNCTION_LIST(F)
05759 { NULL, NULL, NULL, 0, -1 }
05760 };
05761
05762 #undef F
05763
05764
05765 Runtime::Function* Runtime::FunctionForId(FunctionId fid) {
05766 ASSERT(0 <= fid && fid < kNofFunctions);
05767 return &Runtime_functions[fid];
05768 }
05769
05770
05771 Runtime::Function* Runtime::FunctionForName(const char* name) {
05772 for (Function* f = Runtime_functions; f->name != NULL; f++) {
05773 if (strcmp(f->name, name) == 0) {
05774 return f;
05775 }
05776 }
05777 return NULL;
05778 }
05779
05780
05781 void Runtime::PerformGC(Object* result) {
05782 Failure* failure = Failure::cast(result);
05783 if (failure->IsRetryAfterGC()) {
05784
05785
05786 Heap::CollectGarbage(failure->requested(), failure->allocation_space());
05787 } else {
05788
05789
05790 Counters::gc_last_resort_from_js.Increment();
05791 Heap::CollectAllGarbage();
05792 }
05793 }
05794
05795
05796 } }