2014-03-31 12:01:02 +00:00
|
|
|
// Copyright 2014 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/factory.h"
|
2014-03-31 12:01:02 +00:00
|
|
|
|
2016-07-18 15:35:37 +00:00
|
|
|
#include "src/accessors.h"
|
2014-07-07 13:27:37 +00:00
|
|
|
#include "src/allocation-site-scopes.h"
|
2017-07-12 13:06:09 +00:00
|
|
|
#include "src/ast/ast-source-ranges.h"
|
2016-11-28 11:40:22 +00:00
|
|
|
#include "src/ast/ast.h"
|
2014-09-02 13:36:35 +00:00
|
|
|
#include "src/base/bits.h"
|
2015-04-09 22:40:16 +00:00
|
|
|
#include "src/bootstrapper.h"
|
2016-08-23 12:35:20 +00:00
|
|
|
#include "src/compiler.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/conversions.h"
|
2015-09-01 09:25:19 +00:00
|
|
|
#include "src/isolate-inl.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/macro-assembler.h"
|
2017-09-11 13:16:27 +00:00
|
|
|
#include "src/objects/bigint-inl.h"
|
2017-05-23 12:17:09 +00:00
|
|
|
#include "src/objects/debug-objects-inl.h"
|
2017-03-24 14:15:36 +00:00
|
|
|
#include "src/objects/frame-array-inl.h"
|
2017-08-22 18:49:56 +00:00
|
|
|
#include "src/objects/module.h"
|
2017-01-10 16:05:34 +00:00
|
|
|
#include "src/objects/scope-info.h"
|
2017-09-26 21:55:08 +00:00
|
|
|
#include "src/unicode-cache.h"
|
|
|
|
#include "src/unicode-decoder.h"
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2009-05-25 10:05:56 +00:00
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2014-04-15 11:51:34 +00:00
|
|
|
|
2015-09-28 18:08:17 +00:00
|
|
|
// Calls the FUNCTION_CALL function and retries it up to three times
|
|
|
|
// to guarantee that any allocations performed during the call will
|
|
|
|
// succeed if there's enough memory.
|
|
|
|
//
|
|
|
|
// Warning: Do not use the identifiers __object__, __maybe_object__,
|
|
|
|
// __allocation__ or __scope__ in a call to this macro.
|
|
|
|
|
|
|
|
#define RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \
|
|
|
|
if (__allocation__.To(&__object__)) { \
|
|
|
|
DCHECK(__object__ != (ISOLATE)->heap()->exception()); \
|
|
|
|
return Handle<TYPE>(TYPE::cast(__object__), ISOLATE); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE) \
|
|
|
|
do { \
|
|
|
|
AllocationResult __allocation__ = FUNCTION_CALL; \
|
2017-10-13 16:33:03 +00:00
|
|
|
Object* __object__ = nullptr; \
|
2015-09-28 18:08:17 +00:00
|
|
|
RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \
|
|
|
|
/* Two GCs before panicking. In newspace will almost always succeed. */ \
|
|
|
|
for (int __i__ = 0; __i__ < 2; __i__++) { \
|
2016-09-07 10:02:58 +00:00
|
|
|
(ISOLATE)->heap()->CollectGarbage( \
|
|
|
|
__allocation__.RetrySpace(), \
|
|
|
|
GarbageCollectionReason::kAllocationFailure); \
|
2015-09-28 18:08:17 +00:00
|
|
|
__allocation__ = FUNCTION_CALL; \
|
|
|
|
RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \
|
|
|
|
} \
|
|
|
|
(ISOLATE)->counters()->gc_last_resort_from_handles()->Increment(); \
|
2016-09-07 10:02:58 +00:00
|
|
|
(ISOLATE)->heap()->CollectAllAvailableGarbage( \
|
|
|
|
GarbageCollectionReason::kLastResort); \
|
2015-09-28 18:08:17 +00:00
|
|
|
{ \
|
|
|
|
AlwaysAllocateScope __scope__(ISOLATE); \
|
|
|
|
__allocation__ = FUNCTION_CALL; \
|
|
|
|
} \
|
|
|
|
RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \
|
|
|
|
/* TODO(1181417): Fix this. */ \
|
|
|
|
v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); \
|
|
|
|
return Handle<TYPE>(); \
|
|
|
|
} while (false)
|
|
|
|
|
2014-04-15 11:51:34 +00:00
|
|
|
template<typename T>
|
|
|
|
Handle<T> Factory::New(Handle<Map> map, AllocationSpace space) {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->Allocate(*map, space),
|
|
|
|
T);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
Handle<T> Factory::New(Handle<Map> map,
|
|
|
|
AllocationSpace space,
|
|
|
|
Handle<AllocationSite> allocation_site) {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->Allocate(*map, space, *allocation_site),
|
|
|
|
T);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-17 13:15:22 +00:00
|
|
|
Handle<HeapObject> Factory::NewFillerObject(int size,
|
|
|
|
bool double_align,
|
|
|
|
AllocationSpace space) {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateFillerObject(size, double_align, space),
|
|
|
|
HeapObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-07 10:42:45 +00:00
|
|
|
Handle<PrototypeInfo> Factory::NewPrototypeInfo() {
|
|
|
|
Handle<PrototypeInfo> result =
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<PrototypeInfo>::cast(NewStruct(PROTOTYPE_INFO_TYPE, TENURED));
|
2015-04-07 10:42:45 +00:00
|
|
|
result->set_prototype_users(WeakFixedArray::Empty());
|
2015-08-08 22:56:15 +00:00
|
|
|
result->set_registry_slot(PrototypeInfo::UNREGISTERED);
|
2017-11-07 15:06:26 +00:00
|
|
|
result->set_validity_cell(Smi::FromInt(Map::kPrototypeChainValid));
|
2016-06-08 14:43:22 +00:00
|
|
|
result->set_bit_field(0);
|
2015-04-07 10:42:45 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-08-30 04:21:29 +00:00
|
|
|
Handle<EnumCache> Factory::NewEnumCache(Handle<FixedArray> keys,
|
|
|
|
Handle<FixedArray> indices) {
|
2017-08-30 09:54:45 +00:00
|
|
|
return Handle<EnumCache>::cast(NewTuple2(keys, indices, TENURED));
|
2017-08-30 04:21:29 +00:00
|
|
|
}
|
|
|
|
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<Tuple2> Factory::NewTuple2(Handle<Object> value1, Handle<Object> value2,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
Handle<Tuple2> result =
|
|
|
|
Handle<Tuple2>::cast(NewStruct(TUPLE2_TYPE, pretenure));
|
2016-12-02 10:03:18 +00:00
|
|
|
result->set_value1(*value1);
|
|
|
|
result->set_value2(*value2);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-10-13 16:18:53 +00:00
|
|
|
Handle<Tuple3> Factory::NewTuple3(Handle<Object> value1, Handle<Object> value2,
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<Object> value3,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
Handle<Tuple3> result =
|
|
|
|
Handle<Tuple3>::cast(NewStruct(TUPLE3_TYPE, pretenure));
|
2016-10-13 16:18:53 +00:00
|
|
|
result->set_value1(*value1);
|
|
|
|
result->set_value2(*value2);
|
|
|
|
result->set_value3(*value3);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-09-01 15:03:44 +00:00
|
|
|
Handle<ContextExtension> Factory::NewContextExtension(
|
|
|
|
Handle<ScopeInfo> scope_info, Handle<Object> extension) {
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<ContextExtension> result = Handle<ContextExtension>::cast(
|
|
|
|
NewStruct(CONTEXT_EXTENSION_TYPE, TENURED));
|
[es6] Parameter scopes for sloppy eval
This CL is a nightmare! For the utterly irrelevant edge case of a sloppy function with non-simple parameters and a call to direct eval, like here,
let x = 1;
function f(g = () => x) {
var y
eval("var x = 2")
return g() + x // f() = 3
}
we have to do all of the following, on top of the declaration block ("varblock") contexts we already introduce around the body:
- Introduce the ability for varblock contexts to have both a ScopeInfo and an extension object (e.g., the body varblock in the example will contain both a static var y and a dynamic var x). No other scope needs that. Since there are no context slots left, a special new struct is introduced that pairs up scope info and extension object.
- When declaring lookup slots in the runtime, this new struct is allocated in the case where an extension object has to be added to a block scope (at which point the block's extension slot still contains a plain ScopeInfo).
- While at it, introduce some abstraction to access context extension slots in a more controlled manner, in order to keep special-casing to a minimum.
- Make sure that even empty varblock contexts do not get optimised away when they contain a sloppy eval, so that they can host the potential extension object.
- Extend dynamic search for declaration contexts (used by sloppy direct eval) to recognize varblock contexts.
- In the parser, if a function has a sloppy direct eval, introduce an additional varblock scope around each non-simple (desugared) parameter, as required by the spec to contain possible dynamic var bindings.
- In the pattern rewriter, add the ability to hoist the named variables the pattern declares to an outer scope. That is required because the actual destructuring has to be evaluated inside the protecting varblock scope, but the bindings that the desugaring introduces are in the outer scope.
- ScopeInfos need to save the information whether a block is a varblock, to make sloppy eval calls work correctly that deserialise them as part of the scope chain.
- Add the ability to materialize block scopes with extension objects in the debugger. Likewise, enable setting extension variables in block scopes via the debugger interface.
- While at it, refactor and unify some respective code in the debugger.
Sorry, this CL is large. I could try to split it up, but everything is rather entangled.
@mstarzinger: Please review the changes to contexts.
@yangguo: Please have a look at the debugger stuff.
R=littledan@chromium.org, mstarzinger@chromium.org, yangguo@chromium.org
BUG=v8:811,v8:2160
LOG=N
Review URL: https://codereview.chromium.org/1292753007
Cr-Commit-Position: refs/heads/master@{#30295}
2015-08-21 10:58:35 +00:00
|
|
|
result->set_scope_info(*scope_info);
|
|
|
|
result->set_extension(*extension);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-12-16 10:57:06 +00:00
|
|
|
Handle<ConstantElementsPair> Factory::NewConstantElementsPair(
|
|
|
|
ElementsKind elements_kind, Handle<FixedArrayBase> constant_values) {
|
2017-04-18 12:46:39 +00:00
|
|
|
Handle<ConstantElementsPair> result =
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<ConstantElementsPair>::cast(NewStruct(TUPLE2_TYPE, TENURED));
|
2016-12-16 10:57:06 +00:00
|
|
|
result->set_elements_kind(elements_kind);
|
|
|
|
result->set_constant_values(*constant_values);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-09-22 09:57:29 +00:00
|
|
|
Handle<TemplateObjectDescription> Factory::NewTemplateObjectDescription(
|
|
|
|
int hash, Handle<FixedArray> raw_strings,
|
|
|
|
Handle<FixedArray> cooked_strings) {
|
|
|
|
DCHECK_EQ(raw_strings->length(), cooked_strings->length());
|
|
|
|
DCHECK_LT(0, raw_strings->length());
|
|
|
|
Handle<TemplateObjectDescription> result =
|
|
|
|
Handle<TemplateObjectDescription>::cast(NewStruct(TUPLE3_TYPE, TENURED));
|
|
|
|
result->set_hash(hash);
|
|
|
|
result->set_raw_strings(*raw_strings);
|
|
|
|
result->set_cooked_strings(*cooked_strings);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-08-11 10:47:24 +00:00
|
|
|
Handle<Oddball> Factory::NewOddball(Handle<Map> map, const char* to_string,
|
2016-07-19 06:13:34 +00:00
|
|
|
Handle<Object> to_number,
|
2015-08-11 10:47:24 +00:00
|
|
|
const char* type_of, byte kind) {
|
2015-04-07 11:31:57 +00:00
|
|
|
Handle<Oddball> oddball = New<Oddball>(map, OLD_SPACE);
|
2016-07-19 06:13:34 +00:00
|
|
|
Oddball::Initialize(isolate(), oddball, to_string, to_number, type_of, kind);
|
2014-04-16 14:15:32 +00:00
|
|
|
return oddball;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_LE(0, size);
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateFixedArray(size, pretenure),
|
|
|
|
FixedArray);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 20:56:40 +00:00
|
|
|
Handle<PropertyArray> Factory::NewPropertyArray(int size,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
DCHECK_LE(0, size);
|
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
|
|
|
isolate()->heap()->AllocatePropertyArray(size, pretenure),
|
|
|
|
PropertyArray);
|
|
|
|
}
|
|
|
|
|
2016-11-15 18:30:35 +00:00
|
|
|
MaybeHandle<FixedArray> Factory::TryNewFixedArray(int size,
|
|
|
|
PretenureFlag pretenure) {
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_LE(0, size);
|
2016-11-15 18:30:35 +00:00
|
|
|
AllocationResult allocation =
|
|
|
|
isolate()->heap()->AllocateFixedArray(size, pretenure);
|
2017-10-13 16:33:03 +00:00
|
|
|
Object* array = nullptr;
|
2016-11-15 18:30:35 +00:00
|
|
|
if (!allocation.To(&array)) return MaybeHandle<FixedArray>();
|
|
|
|
return Handle<FixedArray>(FixedArray::cast(array), isolate());
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2010-04-14 14:46:15 +00:00
|
|
|
Handle<FixedArray> Factory::NewFixedArrayWithHoles(int size,
|
|
|
|
PretenureFlag pretenure) {
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_LE(0, size);
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
2014-04-14 16:05:19 +00:00
|
|
|
isolate()->heap()->AllocateFixedArrayWithFiller(size,
|
|
|
|
pretenure,
|
|
|
|
*the_hole_value()),
|
2011-03-18 20:35:07 +00:00
|
|
|
FixedArray);
|
2008-10-29 10:02:09 +00:00
|
|
|
}
|
|
|
|
|
2014-03-20 13:01:08 +00:00
|
|
|
Handle<FixedArray> Factory::NewUninitializedFixedArray(int size) {
|
2017-06-22 14:21:51 +00:00
|
|
|
// TODO(ulan): As an experiment this temporarily returns an initialized fixed
|
|
|
|
// array. After getting canary/performance coverage, either remove the
|
|
|
|
// function or revert to returning uninitilized array.
|
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
|
|
|
isolate()->heap()->AllocateFixedArray(size, NOT_TENURED),
|
|
|
|
FixedArray);
|
2014-03-20 13:01:08 +00:00
|
|
|
}
|
|
|
|
|
2017-07-27 12:45:00 +00:00
|
|
|
Handle<FeedbackVector> Factory::NewFeedbackVector(
|
|
|
|
Handle<SharedFunctionInfo> shared, PretenureFlag pretenure) {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(), isolate()->heap()->AllocateFeedbackVector(*shared, pretenure),
|
|
|
|
FeedbackVector);
|
|
|
|
}
|
|
|
|
|
2017-01-20 18:47:55 +00:00
|
|
|
Handle<BoilerplateDescription> Factory::NewBoilerplateDescription(
|
2017-01-24 19:06:03 +00:00
|
|
|
int boilerplate, int all_properties, int index_keys, bool has_seen_proto) {
|
|
|
|
DCHECK_GE(boilerplate, 0);
|
|
|
|
DCHECK_GE(all_properties, index_keys);
|
|
|
|
DCHECK_GE(index_keys, 0);
|
2017-01-20 18:47:55 +00:00
|
|
|
|
2017-01-24 19:06:03 +00:00
|
|
|
int backing_store_size =
|
|
|
|
all_properties - index_keys - (has_seen_proto ? 1 : 0);
|
2017-01-20 18:47:55 +00:00
|
|
|
DCHECK_GE(backing_store_size, 0);
|
|
|
|
bool has_different_size_backing_store = boilerplate != backing_store_size;
|
|
|
|
|
|
|
|
// Space for name and value for every boilerplate property.
|
|
|
|
int size = 2 * boilerplate;
|
|
|
|
|
|
|
|
if (has_different_size_backing_store) {
|
|
|
|
// An extra entry for the backing store size.
|
|
|
|
size++;
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<BoilerplateDescription> description =
|
|
|
|
Handle<BoilerplateDescription>::cast(NewFixedArray(size, TENURED));
|
|
|
|
|
|
|
|
if (has_different_size_backing_store) {
|
2017-01-24 19:06:03 +00:00
|
|
|
DCHECK((boilerplate != (all_properties - index_keys)) || has_seen_proto);
|
2017-01-20 18:47:55 +00:00
|
|
|
description->set_backing_store_size(isolate(), backing_store_size);
|
|
|
|
}
|
|
|
|
return description;
|
|
|
|
}
|
2014-03-20 13:01:08 +00:00
|
|
|
|
2014-04-24 05:29:00 +00:00
|
|
|
Handle<FixedArrayBase> Factory::NewFixedDoubleArray(int size,
|
2014-04-25 16:02:50 +00:00
|
|
|
PretenureFlag pretenure) {
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_LE(0, size);
|
2011-06-09 10:03:35 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateUninitializedFixedDoubleArray(size, pretenure),
|
2014-04-24 05:29:00 +00:00
|
|
|
FixedArrayBase);
|
2011-06-09 10:03:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-24 05:29:00 +00:00
|
|
|
Handle<FixedArrayBase> Factory::NewFixedDoubleArrayWithHoles(
|
2014-04-14 16:05:19 +00:00
|
|
|
int size,
|
|
|
|
PretenureFlag pretenure) {
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_LE(0, size);
|
2014-04-24 05:29:00 +00:00
|
|
|
Handle<FixedArrayBase> array = NewFixedDoubleArray(size, pretenure);
|
|
|
|
if (size > 0) {
|
2016-11-23 09:43:42 +00:00
|
|
|
Handle<FixedDoubleArray>::cast(array)->FillWithHoles(0, size);
|
2014-04-14 16:05:19 +00:00
|
|
|
}
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
2016-08-24 08:48:34 +00:00
|
|
|
Handle<FrameArray> Factory::NewFrameArray(int number_of_frames,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
DCHECK_LE(0, number_of_frames);
|
|
|
|
Handle<FixedArray> result =
|
|
|
|
NewFixedArrayWithHoles(FrameArray::LengthFor(number_of_frames));
|
2016-10-07 13:05:07 +00:00
|
|
|
result->set(FrameArray::kFrameCountIndex, Smi::kZero);
|
2016-08-24 08:48:34 +00:00
|
|
|
return Handle<FrameArray>::cast(result);
|
|
|
|
}
|
2014-04-14 16:05:19 +00:00
|
|
|
|
2017-05-29 09:29:19 +00:00
|
|
|
Handle<SmallOrderedHashSet> Factory::NewSmallOrderedHashSet(
|
|
|
|
int size, PretenureFlag pretenure) {
|
|
|
|
DCHECK_LE(0, size);
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateSmallOrderedHashSet(size, pretenure),
|
|
|
|
SmallOrderedHashSet);
|
|
|
|
}
|
|
|
|
|
2017-06-19 23:19:16 +00:00
|
|
|
Handle<SmallOrderedHashMap> Factory::NewSmallOrderedHashMap(
|
|
|
|
int size, PretenureFlag pretenure) {
|
|
|
|
DCHECK_LE(0, size);
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateSmallOrderedHashMap(size, pretenure),
|
|
|
|
SmallOrderedHashMap);
|
|
|
|
}
|
|
|
|
|
2014-04-04 20:41:57 +00:00
|
|
|
Handle<OrderedHashSet> Factory::NewOrderedHashSet() {
|
2014-12-10 18:47:24 +00:00
|
|
|
return OrderedHashSet::Allocate(isolate(), OrderedHashSet::kMinCapacity);
|
2014-04-04 20:41:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<OrderedHashMap> Factory::NewOrderedHashMap() {
|
2014-12-10 18:47:24 +00:00
|
|
|
return OrderedHashMap::Allocate(isolate(), OrderedHashMap::kMinCapacity);
|
2014-04-04 20:41:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-10 16:11:33 +00:00
|
|
|
Handle<AccessorPair> Factory::NewAccessorPair() {
|
2014-04-07 10:12:54 +00:00
|
|
|
Handle<AccessorPair> accessors =
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<AccessorPair>::cast(NewStruct(ACCESSOR_PAIR_TYPE, TENURED));
|
2016-05-04 12:37:18 +00:00
|
|
|
accessors->set_getter(*null_value(), SKIP_WRITE_BARRIER);
|
|
|
|
accessors->set_setter(*null_value(), SKIP_WRITE_BARRIER);
|
2014-04-07 10:12:54 +00:00
|
|
|
return accessors;
|
2012-01-10 16:11:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-20 12:57:23 +00:00
|
|
|
Handle<TypeFeedbackInfo> Factory::NewTypeFeedbackInfo() {
|
2014-04-07 10:12:54 +00:00
|
|
|
Handle<TypeFeedbackInfo> info =
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<TypeFeedbackInfo>::cast(NewStruct(TUPLE3_TYPE, TENURED));
|
2014-04-07 10:12:54 +00:00
|
|
|
info->initialize_storage();
|
|
|
|
return info;
|
2012-02-20 12:57:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-28 17:03:34 +00:00
|
|
|
// Internalized strings are created in the old generation (data space).
|
|
|
|
Handle<String> Factory::InternalizeUtf8String(Vector<const char> string) {
|
2014-01-17 10:27:57 +00:00
|
|
|
Utf8StringKey key(string, isolate()->heap()->HashSeed());
|
|
|
|
return InternalizeStringWithKey(&key);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-05 09:52:11 +00:00
|
|
|
|
2013-02-28 17:03:34 +00:00
|
|
|
Handle<String> Factory::InternalizeOneByteString(Vector<const uint8_t> string) {
|
2014-01-17 10:27:57 +00:00
|
|
|
OneByteStringKey key(string, isolate()->heap()->HashSeed());
|
|
|
|
return InternalizeStringWithKey(&key);
|
2010-12-22 20:14:19 +00:00
|
|
|
}
|
|
|
|
|
2011-05-24 12:16:23 +00:00
|
|
|
|
2013-02-28 17:03:34 +00:00
|
|
|
Handle<String> Factory::InternalizeOneByteString(
|
|
|
|
Handle<SeqOneByteString> string, int from, int length) {
|
2014-08-19 08:53:38 +00:00
|
|
|
SeqOneByteSubStringKey key(string, from, length);
|
2014-01-17 10:27:57 +00:00
|
|
|
return InternalizeStringWithKey(&key);
|
2011-05-24 12:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-28 17:03:34 +00:00
|
|
|
Handle<String> Factory::InternalizeTwoByteString(Vector<const uc16> string) {
|
2014-01-17 10:27:57 +00:00
|
|
|
TwoByteStringKey key(string, isolate()->heap()->HashSeed());
|
|
|
|
return InternalizeStringWithKey(&key);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StringTableKey>
|
|
|
|
Handle<String> Factory::InternalizeStringWithKey(StringTableKey* key) {
|
2014-04-23 15:43:39 +00:00
|
|
|
return StringTable::LookupKey(isolate(), key);
|
2010-12-22 20:14:19 +00:00
|
|
|
}
|
|
|
|
|
2014-04-17 13:27:02 +00:00
|
|
|
MaybeHandle<String> Factory::NewStringFromOneByte(Vector<const uint8_t> string,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
int length = string.length();
|
2017-01-19 13:27:59 +00:00
|
|
|
if (length == 0) return empty_string();
|
2014-06-18 13:26:02 +00:00
|
|
|
if (length == 1) return LookupSingleCharacterStringFromCode(string[0]);
|
2014-04-17 13:27:02 +00:00
|
|
|
Handle<SeqOneByteString> result;
|
|
|
|
ASSIGN_RETURN_ON_EXCEPTION(
|
2011-03-18 20:35:07 +00:00
|
|
|
isolate(),
|
2014-04-17 13:27:02 +00:00
|
|
|
result,
|
|
|
|
NewRawOneByteString(string.length(), pretenure),
|
2011-03-18 20:35:07 +00:00
|
|
|
String);
|
2014-04-17 13:27:02 +00:00
|
|
|
|
|
|
|
DisallowHeapAllocation no_gc;
|
|
|
|
// Copy the characters into the new object.
|
|
|
|
CopyChars(SeqOneByteString::cast(*result)->GetChars(),
|
|
|
|
string.start(),
|
|
|
|
length);
|
|
|
|
return result;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2014-04-17 13:27:02 +00:00
|
|
|
MaybeHandle<String> Factory::NewStringFromUtf8(Vector<const char> string,
|
|
|
|
PretenureFlag pretenure) {
|
2014-04-16 18:28:03 +00:00
|
|
|
// Check for ASCII first since this is the common case.
|
|
|
|
const char* start = string.start();
|
|
|
|
int length = string.length();
|
|
|
|
int non_ascii_start = String::NonAsciiStart(start, length);
|
|
|
|
if (non_ascii_start >= length) {
|
|
|
|
// If the string is ASCII, we do not need to convert the characters
|
|
|
|
// since UTF8 is backwards compatible with ASCII.
|
|
|
|
return NewStringFromOneByte(Vector<const uint8_t>::cast(string), pretenure);
|
|
|
|
}
|
2014-06-18 13:26:02 +00:00
|
|
|
|
2014-04-16 18:28:03 +00:00
|
|
|
// Non-ASCII and we need to decode.
|
2014-06-18 13:26:02 +00:00
|
|
|
Access<UnicodeCache::Utf8Decoder>
|
|
|
|
decoder(isolate()->unicode_cache()->utf8_decoder());
|
|
|
|
decoder->Reset(string.start() + non_ascii_start,
|
|
|
|
length - non_ascii_start);
|
2015-02-05 07:54:24 +00:00
|
|
|
int utf16_length = static_cast<int>(decoder->Utf16Length());
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_GT(utf16_length, 0);
|
2014-06-18 13:26:02 +00:00
|
|
|
// Allocate string.
|
|
|
|
Handle<SeqTwoByteString> result;
|
|
|
|
ASSIGN_RETURN_ON_EXCEPTION(
|
|
|
|
isolate(), result,
|
|
|
|
NewRawTwoByteString(non_ascii_start + utf16_length, pretenure),
|
2011-03-18 20:35:07 +00:00
|
|
|
String);
|
2014-09-10 12:38:12 +00:00
|
|
|
// Copy ASCII portion.
|
2014-06-18 13:26:02 +00:00
|
|
|
uint16_t* data = result->GetChars();
|
|
|
|
const char* ascii_data = string.start();
|
|
|
|
for (int i = 0; i < non_ascii_start; i++) {
|
|
|
|
*data++ = *ascii_data++;
|
|
|
|
}
|
|
|
|
// Now write the remainder.
|
|
|
|
decoder->WriteUtf16(data, utf16_length);
|
[wasm] Use a Managed<WasmModule> to hold metadata about modules.
This CL refactors the handling of metadata associated with WebAssembly
modules to reduce the duplicate marshalling of data from the C++ world
to the JavaScript world. It does this by wrapping the C++ WasmModule*
object in a Foreign that is rooted from the on-heap WasmCompiledModule
(which is itself just a FixedArray). Upon serialization, the C++ object
is ignored and the original WASM wire bytes are serialized. Upon
deserialization, the C++ object is reconstituted by reparsing the bytes.
This is motivated by increasing complications in implementing the JS
API, in particular WebAssembly.Table, which must perform signature
canonicalization across instances.
Additionally, this CL implements the proper base + offset initialization
behavior for tables.
R=rossberg@chromium.org,bradnelson@chromium.org,mtrofin@chromium.org,yangguo@chromium.org
BUG=v8:5507, chromium:575167, chromium:657316
Review-Url: https://chromiumcodereview.appspot.com/2424623002
Cr-Commit-Position: refs/heads/master@{#40434}
2016-10-19 13:06:44 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
MaybeHandle<String> Factory::NewStringFromUtf8SubString(
|
|
|
|
Handle<SeqOneByteString> str, int begin, int length,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
// Check for ASCII first since this is the common case.
|
|
|
|
const char* start = reinterpret_cast<const char*>(str->GetChars() + begin);
|
|
|
|
int non_ascii_start = String::NonAsciiStart(start, length);
|
|
|
|
if (non_ascii_start >= length) {
|
|
|
|
// If the string is ASCII, we can just make a substring.
|
|
|
|
// TODO(v8): the pretenure flag is ignored in this case.
|
|
|
|
return NewSubString(str, begin, begin + length);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Non-ASCII and we need to decode.
|
|
|
|
Access<UnicodeCache::Utf8Decoder> decoder(
|
|
|
|
isolate()->unicode_cache()->utf8_decoder());
|
|
|
|
decoder->Reset(start + non_ascii_start, length - non_ascii_start);
|
|
|
|
int utf16_length = static_cast<int>(decoder->Utf16Length());
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_GT(utf16_length, 0);
|
[wasm] Use a Managed<WasmModule> to hold metadata about modules.
This CL refactors the handling of metadata associated with WebAssembly
modules to reduce the duplicate marshalling of data from the C++ world
to the JavaScript world. It does this by wrapping the C++ WasmModule*
object in a Foreign that is rooted from the on-heap WasmCompiledModule
(which is itself just a FixedArray). Upon serialization, the C++ object
is ignored and the original WASM wire bytes are serialized. Upon
deserialization, the C++ object is reconstituted by reparsing the bytes.
This is motivated by increasing complications in implementing the JS
API, in particular WebAssembly.Table, which must perform signature
canonicalization across instances.
Additionally, this CL implements the proper base + offset initialization
behavior for tables.
R=rossberg@chromium.org,bradnelson@chromium.org,mtrofin@chromium.org,yangguo@chromium.org
BUG=v8:5507, chromium:575167, chromium:657316
Review-Url: https://chromiumcodereview.appspot.com/2424623002
Cr-Commit-Position: refs/heads/master@{#40434}
2016-10-19 13:06:44 +00:00
|
|
|
// Allocate string.
|
|
|
|
Handle<SeqTwoByteString> result;
|
|
|
|
ASSIGN_RETURN_ON_EXCEPTION(
|
|
|
|
isolate(), result,
|
|
|
|
NewRawTwoByteString(non_ascii_start + utf16_length, pretenure), String);
|
|
|
|
|
|
|
|
// Reset the decoder, because the original {str} may have moved.
|
|
|
|
const char* ascii_data =
|
|
|
|
reinterpret_cast<const char*>(str->GetChars() + begin);
|
|
|
|
decoder->Reset(ascii_data + non_ascii_start, length - non_ascii_start);
|
|
|
|
// Copy ASCII portion.
|
|
|
|
uint16_t* data = result->GetChars();
|
|
|
|
for (int i = 0; i < non_ascii_start; i++) {
|
|
|
|
*data++ = *ascii_data++;
|
|
|
|
}
|
|
|
|
// Now write the remainder.
|
|
|
|
decoder->WriteUtf16(data, utf16_length);
|
2014-06-18 13:26:02 +00:00
|
|
|
return result;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2016-06-15 06:42:47 +00:00
|
|
|
MaybeHandle<String> Factory::NewStringFromTwoByte(const uc16* string,
|
|
|
|
int length,
|
2014-04-17 13:27:02 +00:00
|
|
|
PretenureFlag pretenure) {
|
2017-01-19 13:27:59 +00:00
|
|
|
if (length == 0) return empty_string();
|
2016-06-15 06:42:47 +00:00
|
|
|
if (String::IsOneByte(string, length)) {
|
2014-08-11 14:04:37 +00:00
|
|
|
if (length == 1) return LookupSingleCharacterStringFromCode(string[0]);
|
2014-06-18 13:26:02 +00:00
|
|
|
Handle<SeqOneByteString> result;
|
|
|
|
ASSIGN_RETURN_ON_EXCEPTION(
|
|
|
|
isolate(),
|
|
|
|
result,
|
|
|
|
NewRawOneByteString(length, pretenure),
|
|
|
|
String);
|
2016-06-15 06:42:47 +00:00
|
|
|
CopyChars(result->GetChars(), string, length);
|
2014-06-18 13:26:02 +00:00
|
|
|
return result;
|
|
|
|
} else {
|
|
|
|
Handle<SeqTwoByteString> result;
|
|
|
|
ASSIGN_RETURN_ON_EXCEPTION(
|
|
|
|
isolate(),
|
|
|
|
result,
|
|
|
|
NewRawTwoByteString(length, pretenure),
|
|
|
|
String);
|
2016-06-15 06:42:47 +00:00
|
|
|
CopyChars(result->GetChars(), string, length);
|
2014-06-18 13:26:02 +00:00
|
|
|
return result;
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2016-06-15 06:42:47 +00:00
|
|
|
MaybeHandle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
return NewStringFromTwoByte(string.start(), string.length(), pretenure);
|
|
|
|
}
|
|
|
|
|
|
|
|
MaybeHandle<String> Factory::NewStringFromTwoByte(
|
|
|
|
const ZoneVector<uc16>* string, PretenureFlag pretenure) {
|
|
|
|
return NewStringFromTwoByte(string->data(), static_cast<int>(string->size()),
|
|
|
|
pretenure);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2014-04-25 13:59:33 +00:00
|
|
|
Handle<String> Factory::NewInternalizedStringFromUtf8(Vector<const char> str,
|
|
|
|
int chars,
|
|
|
|
uint32_t hash_field) {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateInternalizedStringFromUtf8(
|
|
|
|
str, chars, hash_field),
|
|
|
|
String);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MUST_USE_RESULT Handle<String> Factory::NewOneByteInternalizedString(
|
|
|
|
Vector<const uint8_t> str,
|
|
|
|
uint32_t hash_field) {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateOneByteInternalizedString(str, hash_field),
|
|
|
|
String);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-19 08:53:38 +00:00
|
|
|
MUST_USE_RESULT Handle<String> Factory::NewOneByteInternalizedSubString(
|
|
|
|
Handle<SeqOneByteString> string, int offset, int length,
|
|
|
|
uint32_t hash_field) {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(), isolate()->heap()->AllocateOneByteInternalizedString(
|
|
|
|
Vector<const uint8_t>(string->GetChars() + offset, length),
|
|
|
|
hash_field),
|
|
|
|
String);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-25 13:59:33 +00:00
|
|
|
MUST_USE_RESULT Handle<String> Factory::NewTwoByteInternalizedString(
|
|
|
|
Vector<const uc16> str,
|
|
|
|
uint32_t hash_field) {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateTwoByteInternalizedString(str, hash_field),
|
|
|
|
String);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<String> Factory::NewInternalizedStringImpl(
|
2014-04-25 16:02:50 +00:00
|
|
|
Handle<String> string, int chars, uint32_t hash_field) {
|
2014-04-25 13:59:33 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
2014-04-25 16:02:50 +00:00
|
|
|
isolate()->heap()->AllocateInternalizedStringImpl(
|
|
|
|
*string, chars, hash_field),
|
2014-04-25 13:59:33 +00:00
|
|
|
String);
|
|
|
|
}
|
|
|
|
|
2017-01-19 13:27:59 +00:00
|
|
|
namespace {
|
2014-04-25 13:59:33 +00:00
|
|
|
|
2017-01-19 13:27:59 +00:00
|
|
|
MaybeHandle<Map> GetInternalizedStringMap(Factory* f, Handle<String> string) {
|
2014-04-25 13:59:33 +00:00
|
|
|
switch (string->map()->instance_type()) {
|
2017-01-11 14:59:35 +00:00
|
|
|
case STRING_TYPE:
|
2017-01-19 13:27:59 +00:00
|
|
|
return f->internalized_string_map();
|
2014-09-10 12:38:12 +00:00
|
|
|
case ONE_BYTE_STRING_TYPE:
|
2017-01-19 13:27:59 +00:00
|
|
|
return f->one_byte_internalized_string_map();
|
2017-01-11 14:59:35 +00:00
|
|
|
case EXTERNAL_STRING_TYPE:
|
2017-01-19 13:27:59 +00:00
|
|
|
return f->external_internalized_string_map();
|
2014-09-10 12:38:12 +00:00
|
|
|
case EXTERNAL_ONE_BYTE_STRING_TYPE:
|
2017-01-19 13:27:59 +00:00
|
|
|
return f->external_one_byte_internalized_string_map();
|
2014-04-25 13:59:33 +00:00
|
|
|
case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
|
2017-01-19 13:27:59 +00:00
|
|
|
return f->external_internalized_string_with_one_byte_data_map();
|
2014-04-25 13:59:33 +00:00
|
|
|
case SHORT_EXTERNAL_STRING_TYPE:
|
2017-01-19 13:27:59 +00:00
|
|
|
return f->short_external_internalized_string_map();
|
2014-09-10 12:38:12 +00:00
|
|
|
case SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE:
|
2017-01-19 13:27:59 +00:00
|
|
|
return f->short_external_one_byte_internalized_string_map();
|
2014-04-25 13:59:33 +00:00
|
|
|
case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
|
2017-01-19 13:27:59 +00:00
|
|
|
return f->short_external_internalized_string_with_one_byte_data_map();
|
2014-04-25 13:59:33 +00:00
|
|
|
default: return MaybeHandle<Map>(); // No match found.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-19 13:27:59 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
MaybeHandle<Map> Factory::InternalizedStringMapForString(
|
|
|
|
Handle<String> string) {
|
|
|
|
// If the string is in new space it cannot be used as internalized.
|
|
|
|
if (isolate()->heap()->InNewSpace(*string)) return MaybeHandle<Map>();
|
|
|
|
|
|
|
|
return GetInternalizedStringMap(this, string);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class StringClass>
|
|
|
|
Handle<StringClass> Factory::InternalizeExternalString(Handle<String> string) {
|
|
|
|
Handle<StringClass> cast_string = Handle<StringClass>::cast(string);
|
|
|
|
Handle<Map> map = GetInternalizedStringMap(this, string).ToHandleChecked();
|
|
|
|
Handle<StringClass> external_string = New<StringClass>(map, OLD_SPACE);
|
|
|
|
external_string->set_length(cast_string->length());
|
|
|
|
external_string->set_hash_field(cast_string->hash_field());
|
|
|
|
external_string->set_resource(nullptr);
|
|
|
|
isolate()->heap()->RegisterExternalString(*external_string);
|
|
|
|
return external_string;
|
|
|
|
}
|
|
|
|
|
|
|
|
template Handle<ExternalOneByteString>
|
|
|
|
Factory::InternalizeExternalString<ExternalOneByteString>(Handle<String>);
|
|
|
|
template Handle<ExternalTwoByteString>
|
|
|
|
Factory::InternalizeExternalString<ExternalTwoByteString>(Handle<String>);
|
2014-04-25 13:59:33 +00:00
|
|
|
|
2014-04-03 12:30:08 +00:00
|
|
|
MaybeHandle<SeqOneByteString> Factory::NewRawOneByteString(
|
|
|
|
int length, PretenureFlag pretenure) {
|
2014-06-18 13:26:02 +00:00
|
|
|
if (length > String::kMaxLength || length < 0) {
|
2014-09-01 09:11:44 +00:00
|
|
|
THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), SeqOneByteString);
|
2014-06-18 13:26:02 +00:00
|
|
|
}
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_GT(length, 0); // Use Factory::empty_string() instead.
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
2012-11-21 10:01:05 +00:00
|
|
|
isolate()->heap()->AllocateRawOneByteString(length, pretenure),
|
2012-11-15 13:31:27 +00:00
|
|
|
SeqOneByteString);
|
2010-07-05 12:49:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-03 12:30:08 +00:00
|
|
|
MaybeHandle<SeqTwoByteString> Factory::NewRawTwoByteString(
|
|
|
|
int length, PretenureFlag pretenure) {
|
2014-06-18 13:26:02 +00:00
|
|
|
if (length > String::kMaxLength || length < 0) {
|
2014-09-01 09:11:44 +00:00
|
|
|
THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), SeqTwoByteString);
|
2014-06-18 13:26:02 +00:00
|
|
|
}
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_GT(length, 0); // Use Factory::empty_string() instead.
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateRawTwoByteString(length, pretenure),
|
2011-06-27 09:02:34 +00:00
|
|
|
SeqTwoByteString);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-23 15:43:39 +00:00
|
|
|
Handle<String> Factory::LookupSingleCharacterStringFromCode(uint32_t code) {
|
|
|
|
if (code <= String::kMaxOneByteCharCodeU) {
|
|
|
|
{
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
Object* value = single_character_string_cache()->get(code);
|
|
|
|
if (value != *undefined_value()) {
|
|
|
|
return handle(String::cast(value), isolate());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint8_t buffer[1];
|
|
|
|
buffer[0] = static_cast<uint8_t>(code);
|
|
|
|
Handle<String> result =
|
|
|
|
InternalizeOneByteString(Vector<const uint8_t>(buffer, 1));
|
|
|
|
single_character_string_cache()->set(code, *result);
|
|
|
|
return result;
|
|
|
|
}
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_LE(code, String::kMaxUtf16CodeUnitU);
|
2014-04-23 15:43:39 +00:00
|
|
|
|
|
|
|
Handle<SeqTwoByteString> result = NewRawTwoByteString(1).ToHandleChecked();
|
|
|
|
result->SeqTwoByteStringSet(0, static_cast<uint16_t>(code));
|
|
|
|
return result;
|
2014-04-08 06:45:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-23 12:37:56 +00:00
|
|
|
// Returns true for a character in a range. Both limits are inclusive.
|
|
|
|
static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
|
|
|
|
// This makes uses of the the unsigned wraparound.
|
|
|
|
return character - from <= to - from;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline Handle<String> MakeOrFindTwoCharacterString(Isolate* isolate,
|
|
|
|
uint16_t c1,
|
|
|
|
uint16_t c2) {
|
|
|
|
// Numeric strings have a different hash algorithm not known by
|
|
|
|
// LookupTwoCharsStringIfExists, so we skip this step for such strings.
|
|
|
|
if (!Between(c1, '0', '9') || !Between(c2, '0', '9')) {
|
2014-04-30 17:27:40 +00:00
|
|
|
Handle<String> result;
|
|
|
|
if (StringTable::LookupTwoCharsStringIfExists(isolate, c1, c2).
|
|
|
|
ToHandle(&result)) {
|
|
|
|
return result;
|
2013-12-23 12:37:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we know the length is 2, we might as well make use of that fact
|
|
|
|
// when building the new string.
|
|
|
|
if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
|
|
|
|
// We can do this.
|
2017-07-12 13:59:52 +00:00
|
|
|
DCHECK(base::bits::IsPowerOfTwo(String::kMaxOneByteCharCodeU +
|
|
|
|
1)); // because of this.
|
2014-04-03 12:30:08 +00:00
|
|
|
Handle<SeqOneByteString> str =
|
|
|
|
isolate->factory()->NewRawOneByteString(2).ToHandleChecked();
|
2013-12-23 12:37:56 +00:00
|
|
|
uint8_t* dest = str->GetChars();
|
|
|
|
dest[0] = static_cast<uint8_t>(c1);
|
|
|
|
dest[1] = static_cast<uint8_t>(c2);
|
|
|
|
return str;
|
|
|
|
} else {
|
2014-04-03 12:30:08 +00:00
|
|
|
Handle<SeqTwoByteString> str =
|
|
|
|
isolate->factory()->NewRawTwoByteString(2).ToHandleChecked();
|
2013-12-23 12:37:56 +00:00
|
|
|
uc16* dest = str->GetChars();
|
|
|
|
dest[0] = c1;
|
|
|
|
dest[1] = c2;
|
|
|
|
return str;
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-21 09:24:30 +00:00
|
|
|
template<typename SinkChar, typename StringType>
|
|
|
|
Handle<String> ConcatStringContent(Handle<StringType> result,
|
|
|
|
Handle<String> first,
|
|
|
|
Handle<String> second) {
|
|
|
|
DisallowHeapAllocation pointer_stays_valid;
|
|
|
|
SinkChar* sink = result->GetChars();
|
|
|
|
String::WriteToFlat(*first, sink, 0, first->length());
|
|
|
|
String::WriteToFlat(*second, sink + first->length(), 0, second->length());
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-03 12:30:37 +00:00
|
|
|
MaybeHandle<String> Factory::NewConsString(Handle<String> left,
|
|
|
|
Handle<String> right) {
|
2017-01-19 13:27:59 +00:00
|
|
|
if (left->IsThinString()) {
|
|
|
|
left = handle(Handle<ThinString>::cast(left)->actual(), isolate());
|
|
|
|
}
|
|
|
|
if (right->IsThinString()) {
|
|
|
|
right = handle(Handle<ThinString>::cast(right)->actual(), isolate());
|
|
|
|
}
|
2013-12-23 12:37:56 +00:00
|
|
|
int left_length = left->length();
|
|
|
|
if (left_length == 0) return right;
|
|
|
|
int right_length = right->length();
|
|
|
|
if (right_length == 0) return left;
|
|
|
|
|
|
|
|
int length = left_length + right_length;
|
|
|
|
|
|
|
|
if (length == 2) {
|
|
|
|
uint16_t c1 = left->Get(0);
|
|
|
|
uint16_t c2 = right->Get(0);
|
|
|
|
return MakeOrFindTwoCharacterString(isolate(), c1, c2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure that an out of memory exception is thrown if the length
|
|
|
|
// of the new cons string is too large.
|
|
|
|
if (length > String::kMaxLength || length < 0) {
|
2014-09-01 09:11:44 +00:00
|
|
|
THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), String);
|
2013-12-23 12:37:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool left_is_one_byte = left->IsOneByteRepresentation();
|
|
|
|
bool right_is_one_byte = right->IsOneByteRepresentation();
|
|
|
|
bool is_one_byte = left_is_one_byte && right_is_one_byte;
|
|
|
|
bool is_one_byte_data_in_two_byte_string = false;
|
|
|
|
if (!is_one_byte) {
|
|
|
|
// At least one of the strings uses two-byte representation so we
|
2014-09-10 12:38:12 +00:00
|
|
|
// can't use the fast case code for short one-byte strings below, but
|
|
|
|
// we can try to save memory if all chars actually fit in one-byte.
|
2013-12-23 12:37:56 +00:00
|
|
|
is_one_byte_data_in_two_byte_string =
|
|
|
|
left->HasOnlyOneByteChars() && right->HasOnlyOneByteChars();
|
|
|
|
if (is_one_byte_data_in_two_byte_string) {
|
2014-09-10 12:38:12 +00:00
|
|
|
isolate()->counters()->string_add_runtime_ext_to_one_byte()->Increment();
|
2013-12-23 12:37:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the resulting string is small make a flat string.
|
|
|
|
if (length < ConsString::kMinLength) {
|
|
|
|
// Note that neither of the two inputs can be a slice because:
|
|
|
|
STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(left->IsFlat());
|
|
|
|
DCHECK(right->IsFlat());
|
2013-12-23 12:37:56 +00:00
|
|
|
|
2014-03-25 09:09:24 +00:00
|
|
|
STATIC_ASSERT(ConsString::kMinLength <= String::kMaxLength);
|
2013-12-23 12:37:56 +00:00
|
|
|
if (is_one_byte) {
|
2014-04-03 12:30:08 +00:00
|
|
|
Handle<SeqOneByteString> result =
|
|
|
|
NewRawOneByteString(length).ToHandleChecked();
|
2013-12-23 12:37:56 +00:00
|
|
|
DisallowHeapAllocation no_gc;
|
|
|
|
uint8_t* dest = result->GetChars();
|
|
|
|
// Copy left part.
|
2014-09-10 12:38:12 +00:00
|
|
|
const uint8_t* src =
|
|
|
|
left->IsExternalString()
|
|
|
|
? Handle<ExternalOneByteString>::cast(left)->GetChars()
|
|
|
|
: Handle<SeqOneByteString>::cast(left)->GetChars();
|
2013-12-23 12:37:56 +00:00
|
|
|
for (int i = 0; i < left_length; i++) *dest++ = src[i];
|
|
|
|
// Copy right part.
|
|
|
|
src = right->IsExternalString()
|
2014-09-10 12:38:12 +00:00
|
|
|
? Handle<ExternalOneByteString>::cast(right)->GetChars()
|
|
|
|
: Handle<SeqOneByteString>::cast(right)->GetChars();
|
2013-12-23 12:37:56 +00:00
|
|
|
for (int i = 0; i < right_length; i++) *dest++ = src[i];
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (is_one_byte_data_in_two_byte_string)
|
2014-04-03 12:30:08 +00:00
|
|
|
? ConcatStringContent<uint8_t>(
|
|
|
|
NewRawOneByteString(length).ToHandleChecked(), left, right)
|
|
|
|
: ConcatStringContent<uc16>(
|
|
|
|
NewRawTwoByteString(length).ToHandleChecked(), left, right);
|
2013-12-23 12:37:56 +00:00
|
|
|
}
|
|
|
|
|
2017-03-09 12:25:19 +00:00
|
|
|
bool one_byte = (is_one_byte || is_one_byte_data_in_two_byte_string);
|
|
|
|
return NewConsString(left, right, length, one_byte);
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<String> Factory::NewConsString(Handle<String> left, Handle<String> right,
|
|
|
|
int length, bool one_byte) {
|
|
|
|
DCHECK(!left->IsThinString());
|
|
|
|
DCHECK(!right->IsThinString());
|
|
|
|
DCHECK_GE(length, ConsString::kMinLength);
|
|
|
|
DCHECK_LE(length, String::kMaxLength);
|
|
|
|
|
2015-09-29 08:08:14 +00:00
|
|
|
Handle<ConsString> result =
|
2017-03-09 12:25:19 +00:00
|
|
|
one_byte ? New<ConsString>(cons_one_byte_string_map(), NEW_SPACE)
|
|
|
|
: New<ConsString>(cons_string_map(), NEW_SPACE);
|
2013-12-23 12:37:56 +00:00
|
|
|
|
|
|
|
DisallowHeapAllocation no_gc;
|
|
|
|
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
|
|
|
|
|
|
|
|
result->set_hash_field(String::kEmptyHashField);
|
|
|
|
result->set_length(length);
|
|
|
|
result->set_first(*left, mode);
|
|
|
|
result->set_second(*right, mode);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-09-21 14:17:42 +00:00
|
|
|
Handle<String> Factory::NewSurrogatePairString(uint16_t lead, uint16_t trail) {
|
|
|
|
DCHECK_GE(lead, 0xD800);
|
|
|
|
DCHECK_LE(lead, 0xDBFF);
|
|
|
|
DCHECK_GE(trail, 0xDC00);
|
|
|
|
DCHECK_LE(trail, 0xDFFF);
|
|
|
|
|
|
|
|
Handle<SeqTwoByteString> str =
|
|
|
|
isolate()->factory()->NewRawTwoByteString(2).ToHandleChecked();
|
|
|
|
uc16* dest = str->GetChars();
|
|
|
|
dest[0] = lead;
|
|
|
|
dest[1] = trail;
|
|
|
|
return str;
|
|
|
|
}
|
2013-12-23 12:37:56 +00:00
|
|
|
|
2011-06-27 09:02:34 +00:00
|
|
|
Handle<String> Factory::NewProperSubString(Handle<String> str,
|
2011-06-22 14:20:23 +00:00
|
|
|
int begin,
|
|
|
|
int end) {
|
2013-12-23 12:37:56 +00:00
|
|
|
#if VERIFY_HEAP
|
|
|
|
if (FLAG_verify_heap) str->StringVerify();
|
|
|
|
#endif
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(begin > 0 || end < str->length());
|
2013-12-23 12:37:56 +00:00
|
|
|
|
2014-04-22 11:19:27 +00:00
|
|
|
str = String::Flatten(str);
|
|
|
|
|
2013-12-23 12:37:56 +00:00
|
|
|
int length = end - begin;
|
|
|
|
if (length <= 0) return empty_string();
|
|
|
|
if (length == 1) {
|
2014-04-08 06:45:53 +00:00
|
|
|
return LookupSingleCharacterStringFromCode(str->Get(begin));
|
2013-12-23 12:37:56 +00:00
|
|
|
}
|
|
|
|
if (length == 2) {
|
|
|
|
// Optimization for 2-byte strings often used as keys in a decompression
|
|
|
|
// dictionary. Check whether we already have the string in the string
|
|
|
|
// table to prevent creation of many unnecessary strings.
|
|
|
|
uint16_t c1 = str->Get(begin);
|
|
|
|
uint16_t c2 = str->Get(begin + 1);
|
|
|
|
return MakeOrFindTwoCharacterString(isolate(), c1, c2);
|
|
|
|
}
|
|
|
|
|
2017-11-02 06:22:13 +00:00
|
|
|
if (!FLAG_string_slices || length < SlicedString::kMinLength) {
|
2013-12-23 12:37:56 +00:00
|
|
|
if (str->IsOneByteRepresentation()) {
|
2014-04-03 12:30:08 +00:00
|
|
|
Handle<SeqOneByteString> result =
|
|
|
|
NewRawOneByteString(length).ToHandleChecked();
|
2013-12-23 12:37:56 +00:00
|
|
|
uint8_t* dest = result->GetChars();
|
|
|
|
DisallowHeapAllocation no_gc;
|
|
|
|
String::WriteToFlat(*str, dest, begin, end);
|
|
|
|
return result;
|
|
|
|
} else {
|
2014-04-03 12:30:08 +00:00
|
|
|
Handle<SeqTwoByteString> result =
|
|
|
|
NewRawTwoByteString(length).ToHandleChecked();
|
2013-12-23 12:37:56 +00:00
|
|
|
uc16* dest = result->GetChars();
|
|
|
|
DisallowHeapAllocation no_gc;
|
|
|
|
String::WriteToFlat(*str, dest, begin, end);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int offset = begin;
|
|
|
|
|
|
|
|
if (str->IsSlicedString()) {
|
|
|
|
Handle<SlicedString> slice = Handle<SlicedString>::cast(str);
|
|
|
|
str = Handle<String>(slice->parent(), isolate());
|
|
|
|
offset += slice->offset();
|
|
|
|
}
|
2017-01-30 18:24:16 +00:00
|
|
|
if (str->IsThinString()) {
|
|
|
|
Handle<ThinString> thin = Handle<ThinString>::cast(str);
|
|
|
|
str = handle(thin->actual(), isolate());
|
|
|
|
}
|
2013-12-23 12:37:56 +00:00
|
|
|
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(str->IsSeqString() || str->IsExternalString());
|
2014-09-10 12:38:12 +00:00
|
|
|
Handle<Map> map = str->IsOneByteRepresentation()
|
|
|
|
? sliced_one_byte_string_map()
|
|
|
|
: sliced_string_map();
|
2014-04-29 07:02:11 +00:00
|
|
|
Handle<SlicedString> slice = New<SlicedString>(map, NEW_SPACE);
|
2013-12-23 12:37:56 +00:00
|
|
|
|
|
|
|
slice->set_hash_field(String::kEmptyHashField);
|
|
|
|
slice->set_length(length);
|
|
|
|
slice->set_parent(*str);
|
|
|
|
slice->set_offset(offset);
|
|
|
|
return slice;
|
2011-06-22 14:20:23 +00:00
|
|
|
}
|
|
|
|
|
2014-09-10 12:38:12 +00:00
|
|
|
MaybeHandle<String> Factory::NewExternalStringFromOneByte(
|
|
|
|
const ExternalOneByteString::Resource* resource) {
|
2014-04-16 13:35:36 +00:00
|
|
|
size_t length = resource->length();
|
|
|
|
if (length > static_cast<size_t>(String::kMaxLength)) {
|
2014-09-01 09:11:44 +00:00
|
|
|
THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), String);
|
2014-04-16 13:35:36 +00:00
|
|
|
}
|
2017-02-08 21:12:45 +00:00
|
|
|
if (length == 0) return empty_string();
|
2014-04-16 13:35:36 +00:00
|
|
|
|
2016-01-12 06:28:09 +00:00
|
|
|
Handle<Map> map;
|
|
|
|
if (resource->IsCompressible()) {
|
|
|
|
// TODO(hajimehoshi): Rename this to 'uncached_external_one_byte_string_map'
|
|
|
|
map = short_external_one_byte_string_map();
|
|
|
|
} else {
|
|
|
|
map = external_one_byte_string_map();
|
|
|
|
}
|
2014-09-10 12:38:12 +00:00
|
|
|
Handle<ExternalOneByteString> external_string =
|
|
|
|
New<ExternalOneByteString>(map, NEW_SPACE);
|
2014-04-16 13:35:36 +00:00
|
|
|
external_string->set_length(static_cast<int>(length));
|
|
|
|
external_string->set_hash_field(String::kEmptyHashField);
|
|
|
|
external_string->set_resource(resource);
|
|
|
|
|
|
|
|
return external_string;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-03 12:41:37 +00:00
|
|
|
MaybeHandle<String> Factory::NewExternalStringFromTwoByte(
|
2011-09-21 13:28:09 +00:00
|
|
|
const ExternalTwoByteString::Resource* resource) {
|
2014-04-16 13:35:36 +00:00
|
|
|
size_t length = resource->length();
|
|
|
|
if (length > static_cast<size_t>(String::kMaxLength)) {
|
2014-09-01 09:11:44 +00:00
|
|
|
THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), String);
|
2014-04-16 13:35:36 +00:00
|
|
|
}
|
2017-02-08 21:12:45 +00:00
|
|
|
if (length == 0) return empty_string();
|
2014-04-16 13:35:36 +00:00
|
|
|
|
|
|
|
// For small strings we check whether the resource contains only
|
|
|
|
// one byte characters. If yes, we use a different string map.
|
|
|
|
static const size_t kOneByteCheckLengthLimit = 32;
|
|
|
|
bool is_one_byte = length <= kOneByteCheckLengthLimit &&
|
|
|
|
String::IsOneByte(resource->data(), static_cast<int>(length));
|
2016-01-12 06:28:09 +00:00
|
|
|
Handle<Map> map;
|
|
|
|
if (resource->IsCompressible()) {
|
|
|
|
// TODO(hajimehoshi): Rename these to 'uncached_external_string_...'.
|
|
|
|
map = is_one_byte ? short_external_string_with_one_byte_data_map()
|
|
|
|
: short_external_string_map();
|
|
|
|
} else {
|
|
|
|
map = is_one_byte ? external_string_with_one_byte_data_map()
|
|
|
|
: external_string_map();
|
|
|
|
}
|
2014-04-16 13:35:36 +00:00
|
|
|
Handle<ExternalTwoByteString> external_string =
|
|
|
|
New<ExternalTwoByteString>(map, NEW_SPACE);
|
|
|
|
external_string->set_length(static_cast<int>(length));
|
|
|
|
external_string->set_hash_field(String::kEmptyHashField);
|
2016-05-19 12:28:30 +00:00
|
|
|
external_string->set_resource(resource);
|
|
|
|
|
|
|
|
return external_string;
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<ExternalOneByteString> Factory::NewNativeSourceString(
|
|
|
|
const ExternalOneByteString::Resource* resource) {
|
|
|
|
size_t length = resource->length();
|
|
|
|
DCHECK_LE(length, static_cast<size_t>(String::kMaxLength));
|
|
|
|
|
|
|
|
Handle<Map> map = native_source_string_map();
|
|
|
|
Handle<ExternalOneByteString> external_string =
|
|
|
|
New<ExternalOneByteString>(map, OLD_SPACE);
|
|
|
|
external_string->set_length(static_cast<int>(length));
|
|
|
|
external_string->set_hash_field(String::kEmptyHashField);
|
2014-04-16 13:35:36 +00:00
|
|
|
external_string->set_resource(resource);
|
|
|
|
|
|
|
|
return external_string;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2016-09-21 14:17:42 +00:00
|
|
|
Handle<JSStringIterator> Factory::NewJSStringIterator(Handle<String> string) {
|
|
|
|
Handle<Map> map(isolate()->native_context()->string_iterator_map(),
|
|
|
|
isolate());
|
|
|
|
Handle<String> flat_string = String::Flatten(string);
|
|
|
|
Handle<JSStringIterator> iterator =
|
|
|
|
Handle<JSStringIterator>::cast(NewJSObjectFromMap(map));
|
|
|
|
iterator->set_string(*flat_string);
|
|
|
|
iterator->set_index(0);
|
|
|
|
|
|
|
|
return iterator;
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2013-03-01 10:34:31 +00:00
|
|
|
Handle<Symbol> Factory::NewSymbol() {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateSymbol(),
|
|
|
|
Symbol);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-29 14:17:24 +00:00
|
|
|
Handle<Symbol> Factory::NewPrivateSymbol() {
|
2014-04-29 13:58:55 +00:00
|
|
|
Handle<Symbol> symbol = NewSymbol();
|
|
|
|
symbol->set_is_private(true);
|
2014-08-12 15:28:20 +00:00
|
|
|
return symbol;
|
|
|
|
}
|
|
|
|
|
2012-08-17 09:03:08 +00:00
|
|
|
Handle<Context> Factory::NewNativeContext() {
|
2015-07-06 16:36:28 +00:00
|
|
|
Handle<FixedArray> array =
|
|
|
|
NewFixedArray(Context::NATIVE_CONTEXT_SLOTS, TENURED);
|
2014-04-07 10:12:54 +00:00
|
|
|
array->set_map_no_write_barrier(*native_context_map());
|
|
|
|
Handle<Context> context = Handle<Context>::cast(array);
|
2015-11-27 16:59:28 +00:00
|
|
|
context->set_native_context(*context);
|
2016-10-07 13:05:07 +00:00
|
|
|
context->set_errors_thrown(Smi::kZero);
|
2016-10-11 06:46:56 +00:00
|
|
|
context->set_math_random_index(Smi::kZero);
|
2015-12-09 08:54:47 +00:00
|
|
|
Handle<WeakCell> weak_cell = NewWeakCell(context);
|
|
|
|
context->set_self_weak_cell(*weak_cell);
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(context->IsNativeContext());
|
2014-04-07 10:12:54 +00:00
|
|
|
return context;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-12 11:34:09 +00:00
|
|
|
Handle<Context> Factory::NewScriptContext(Handle<JSFunction> function,
|
2012-08-27 09:40:26 +00:00
|
|
|
Handle<ScopeInfo> scope_info) {
|
2016-08-19 15:23:57 +00:00
|
|
|
DCHECK_EQ(scope_info->scope_type(), SCRIPT_SCOPE);
|
2014-04-09 08:51:46 +00:00
|
|
|
Handle<FixedArray> array =
|
|
|
|
NewFixedArray(scope_info->ContextLength(), TENURED);
|
2014-11-12 11:34:09 +00:00
|
|
|
array->set_map_no_write_barrier(*script_context_map());
|
2014-04-09 08:51:46 +00:00
|
|
|
Handle<Context> context = Handle<Context>::cast(array);
|
|
|
|
context->set_closure(*function);
|
|
|
|
context->set_previous(function->context());
|
|
|
|
context->set_extension(*scope_info);
|
2015-11-27 16:59:28 +00:00
|
|
|
context->set_native_context(function->native_context());
|
2014-11-12 11:34:09 +00:00
|
|
|
DCHECK(context->IsScriptContext());
|
2014-04-09 08:51:46 +00:00
|
|
|
return context;
|
2012-08-27 09:40:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-12 11:34:09 +00:00
|
|
|
Handle<ScriptContextTable> Factory::NewScriptContextTable() {
|
2014-11-07 16:29:13 +00:00
|
|
|
Handle<FixedArray> array = NewFixedArray(1);
|
2014-11-12 11:34:09 +00:00
|
|
|
array->set_map_no_write_barrier(*script_context_table_map());
|
|
|
|
Handle<ScriptContextTable> context_table =
|
|
|
|
Handle<ScriptContextTable>::cast(array);
|
2014-11-07 16:29:13 +00:00
|
|
|
context_table->set_used(0);
|
|
|
|
return context_table;
|
|
|
|
}
|
|
|
|
|
2016-09-16 16:47:07 +00:00
|
|
|
Handle<Context> Factory::NewModuleContext(Handle<Module> module,
|
2016-09-12 12:54:47 +00:00
|
|
|
Handle<JSFunction> function,
|
|
|
|
Handle<ScopeInfo> scope_info) {
|
2016-08-19 15:23:57 +00:00
|
|
|
DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE);
|
2014-04-07 10:12:54 +00:00
|
|
|
Handle<FixedArray> array =
|
|
|
|
NewFixedArray(scope_info->ContextLength(), TENURED);
|
|
|
|
array->set_map_no_write_barrier(*module_context_map());
|
|
|
|
Handle<Context> context = Handle<Context>::cast(array);
|
2016-09-12 12:54:47 +00:00
|
|
|
context->set_closure(*function);
|
|
|
|
context->set_previous(function->context());
|
|
|
|
context->set_extension(*module);
|
|
|
|
context->set_native_context(function->native_context());
|
|
|
|
DCHECK(context->IsModuleContext());
|
2014-04-07 10:12:54 +00:00
|
|
|
return context;
|
2012-04-16 14:43:27 +00:00
|
|
|
}
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
Handle<Context> Factory::NewFunctionContext(int length,
|
2016-12-20 16:23:19 +00:00
|
|
|
Handle<JSFunction> function,
|
|
|
|
ScopeType scope_type) {
|
|
|
|
DCHECK(function->shared()->scope_info()->scope_type() == scope_type);
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(length >= Context::MIN_CONTEXT_SLOTS);
|
2014-04-09 08:51:46 +00:00
|
|
|
Handle<FixedArray> array = NewFixedArray(length);
|
2016-12-20 16:23:19 +00:00
|
|
|
Handle<Map> map;
|
|
|
|
switch (scope_type) {
|
|
|
|
case EVAL_SCOPE:
|
|
|
|
map = eval_context_map();
|
|
|
|
break;
|
|
|
|
case FUNCTION_SCOPE:
|
|
|
|
map = function_context_map();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
array->set_map_no_write_barrier(*map);
|
2014-04-09 08:51:46 +00:00
|
|
|
Handle<Context> context = Handle<Context>::cast(array);
|
|
|
|
context->set_closure(*function);
|
|
|
|
context->set_previous(function->context());
|
2015-11-30 13:23:04 +00:00
|
|
|
context->set_extension(*the_hole_value());
|
2015-11-27 16:59:28 +00:00
|
|
|
context->set_native_context(function->native_context());
|
2014-04-09 08:51:46 +00:00
|
|
|
return context;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2011-06-29 07:41:42 +00:00
|
|
|
Handle<Context> Factory::NewCatchContext(Handle<JSFunction> function,
|
|
|
|
Handle<Context> previous,
|
2016-09-05 12:10:16 +00:00
|
|
|
Handle<ScopeInfo> scope_info,
|
2011-06-16 06:37:49 +00:00
|
|
|
Handle<String> name,
|
|
|
|
Handle<Object> thrown_object) {
|
2014-04-09 08:51:46 +00:00
|
|
|
STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == Context::THROWN_OBJECT_INDEX);
|
2016-09-05 12:10:16 +00:00
|
|
|
Handle<ContextExtension> extension = NewContextExtension(scope_info, name);
|
2014-04-09 08:51:46 +00:00
|
|
|
Handle<FixedArray> array = NewFixedArray(Context::MIN_CONTEXT_SLOTS + 1);
|
|
|
|
array->set_map_no_write_barrier(*catch_context_map());
|
|
|
|
Handle<Context> context = Handle<Context>::cast(array);
|
|
|
|
context->set_closure(*function);
|
|
|
|
context->set_previous(*previous);
|
2016-09-05 12:10:16 +00:00
|
|
|
context->set_extension(*extension);
|
2015-11-27 16:59:28 +00:00
|
|
|
context->set_native_context(previous->native_context());
|
2014-04-09 08:51:46 +00:00
|
|
|
context->set(Context::THROWN_OBJECT_INDEX, *thrown_object);
|
|
|
|
return context;
|
2011-06-09 11:26:01 +00:00
|
|
|
}
|
|
|
|
|
2016-03-31 05:58:42 +00:00
|
|
|
Handle<Context> Factory::NewDebugEvaluateContext(Handle<Context> previous,
|
2016-09-06 08:27:36 +00:00
|
|
|
Handle<ScopeInfo> scope_info,
|
2016-03-31 05:58:42 +00:00
|
|
|
Handle<JSReceiver> extension,
|
|
|
|
Handle<Context> wrapped,
|
|
|
|
Handle<StringSet> whitelist) {
|
|
|
|
STATIC_ASSERT(Context::WHITE_LIST_INDEX == Context::MIN_CONTEXT_SLOTS + 1);
|
2016-09-14 10:59:42 +00:00
|
|
|
DCHECK(scope_info->IsDebugEvaluateScope());
|
2016-09-06 08:27:36 +00:00
|
|
|
Handle<ContextExtension> context_extension = NewContextExtension(
|
|
|
|
scope_info, extension.is_null() ? Handle<Object>::cast(undefined_value())
|
|
|
|
: Handle<Object>::cast(extension));
|
2016-03-31 05:58:42 +00:00
|
|
|
Handle<FixedArray> array = NewFixedArray(Context::MIN_CONTEXT_SLOTS + 2);
|
|
|
|
array->set_map_no_write_barrier(*debug_evaluate_context_map());
|
|
|
|
Handle<Context> c = Handle<Context>::cast(array);
|
|
|
|
c->set_closure(wrapped.is_null() ? previous->closure() : wrapped->closure());
|
|
|
|
c->set_previous(*previous);
|
|
|
|
c->set_native_context(previous->native_context());
|
2016-09-06 08:27:36 +00:00
|
|
|
c->set_extension(*context_extension);
|
2016-03-31 05:58:42 +00:00
|
|
|
if (!wrapped.is_null()) c->set(Context::WRAPPED_CONTEXT_INDEX, *wrapped);
|
|
|
|
if (!whitelist.is_null()) c->set(Context::WHITE_LIST_INDEX, *whitelist);
|
|
|
|
return c;
|
|
|
|
}
|
2011-06-09 11:26:01 +00:00
|
|
|
|
2011-06-29 07:41:42 +00:00
|
|
|
Handle<Context> Factory::NewWithContext(Handle<JSFunction> function,
|
|
|
|
Handle<Context> previous,
|
2016-09-06 08:27:36 +00:00
|
|
|
Handle<ScopeInfo> scope_info,
|
2014-04-09 08:51:46 +00:00
|
|
|
Handle<JSReceiver> extension) {
|
2016-09-06 08:27:36 +00:00
|
|
|
Handle<ContextExtension> context_extension =
|
|
|
|
NewContextExtension(scope_info, extension);
|
2014-04-09 08:51:46 +00:00
|
|
|
Handle<FixedArray> array = NewFixedArray(Context::MIN_CONTEXT_SLOTS);
|
|
|
|
array->set_map_no_write_barrier(*with_context_map());
|
|
|
|
Handle<Context> context = Handle<Context>::cast(array);
|
|
|
|
context->set_closure(*function);
|
|
|
|
context->set_previous(*previous);
|
2016-09-06 08:27:36 +00:00
|
|
|
context->set_extension(*context_extension);
|
2015-11-27 16:59:28 +00:00
|
|
|
context->set_native_context(previous->native_context());
|
2014-04-09 08:51:46 +00:00
|
|
|
return context;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-16 14:43:27 +00:00
|
|
|
Handle<Context> Factory::NewBlockContext(Handle<JSFunction> function,
|
|
|
|
Handle<Context> previous,
|
|
|
|
Handle<ScopeInfo> scope_info) {
|
2016-08-19 15:23:57 +00:00
|
|
|
DCHECK_EQ(scope_info->scope_type(), BLOCK_SCOPE);
|
2016-01-14 18:04:00 +00:00
|
|
|
Handle<FixedArray> array = NewFixedArray(scope_info->ContextLength());
|
2014-04-09 08:51:46 +00:00
|
|
|
array->set_map_no_write_barrier(*block_context_map());
|
|
|
|
Handle<Context> context = Handle<Context>::cast(array);
|
|
|
|
context->set_closure(*function);
|
|
|
|
context->set_previous(*previous);
|
|
|
|
context->set_extension(*scope_info);
|
2015-11-27 16:59:28 +00:00
|
|
|
context->set_native_context(previous->native_context());
|
2014-04-09 08:51:46 +00:00
|
|
|
return context;
|
2011-08-11 16:29:28 +00:00
|
|
|
}
|
|
|
|
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<Struct> Factory::NewStruct(InstanceType type, PretenureFlag pretenure) {
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
2017-08-30 09:54:45 +00:00
|
|
|
isolate(), isolate()->heap()->AllocateStruct(type, pretenure), Struct);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2013-11-14 17:30:48 +00:00
|
|
|
Handle<AliasedArgumentsEntry> Factory::NewAliasedArgumentsEntry(
|
|
|
|
int aliased_context_slot) {
|
|
|
|
Handle<AliasedArgumentsEntry> entry = Handle<AliasedArgumentsEntry>::cast(
|
2017-08-30 09:54:45 +00:00
|
|
|
NewStruct(ALIASED_ARGUMENTS_ENTRY_TYPE, NOT_TENURED));
|
2013-11-14 17:30:48 +00:00
|
|
|
entry->set_aliased_context_slot(aliased_context_slot);
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-18 15:08:36 +00:00
|
|
|
Handle<AccessorInfo> Factory::NewAccessorInfo() {
|
|
|
|
Handle<AccessorInfo> info =
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<AccessorInfo>::cast(NewStruct(ACCESSOR_INFO_TYPE, TENURED));
|
2017-10-26 15:18:09 +00:00
|
|
|
info->set_name(*empty_string());
|
|
|
|
info->set_flags(0); // Must clear the flags, it was initialized as undefined.
|
2016-05-06 14:10:12 +00:00
|
|
|
info->set_is_sloppy(true);
|
2017-10-26 15:18:09 +00:00
|
|
|
info->set_initial_property_attributes(NONE);
|
2008-07-03 15:10:15 +00:00
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<Script> Factory::NewScript(Handle<String> source) {
|
2009-03-10 12:05:20 +00:00
|
|
|
// Create and initialize script object.
|
2015-03-26 09:50:34 +00:00
|
|
|
Heap* heap = isolate()->heap();
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<Script> script = Handle<Script>::cast(NewStruct(SCRIPT_TYPE, TENURED));
|
2008-07-03 15:10:15 +00:00
|
|
|
script->set_source(*source);
|
2011-03-18 20:35:07 +00:00
|
|
|
script->set_name(heap->undefined_value());
|
2015-03-26 09:50:34 +00:00
|
|
|
script->set_id(isolate()->heap()->NextScriptId());
|
2015-09-28 13:10:13 +00:00
|
|
|
script->set_line_offset(0);
|
|
|
|
script->set_column_offset(0);
|
2011-03-18 20:35:07 +00:00
|
|
|
script->set_context_data(heap->undefined_value());
|
2015-09-28 13:10:13 +00:00
|
|
|
script->set_type(Script::TYPE_NORMAL);
|
2014-10-15 10:11:08 +00:00
|
|
|
script->set_wrapper(heap->undefined_value());
|
2011-03-18 20:35:07 +00:00
|
|
|
script->set_line_ends(heap->undefined_value());
|
|
|
|
script->set_eval_from_shared(heap->undefined_value());
|
2016-04-18 13:20:45 +00:00
|
|
|
script->set_eval_from_position(0);
|
2016-12-15 17:19:55 +00:00
|
|
|
script->set_shared_function_infos(*empty_fixed_array(), SKIP_WRITE_BARRIER);
|
2015-09-28 13:10:13 +00:00
|
|
|
script->set_flags(0);
|
2017-08-30 21:21:13 +00:00
|
|
|
script->set_host_defined_options(*empty_fixed_array());
|
2015-08-20 08:04:41 +00:00
|
|
|
heap->set_script_list(*WeakFixedArray::Add(script_list(), script));
|
2008-07-03 15:10:15 +00:00
|
|
|
return script;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-19 11:47:34 +00:00
|
|
|
Handle<Foreign> Factory::NewForeign(Address addr, PretenureFlag pretenure) {
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
2011-05-19 11:47:34 +00:00
|
|
|
isolate()->heap()->AllocateForeign(addr, pretenure),
|
|
|
|
Foreign);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-19 11:47:34 +00:00
|
|
|
Handle<Foreign> Factory::NewForeign(const AccessorDescriptor* desc) {
|
|
|
|
return NewForeign((Address) desc, TENURED);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-25 11:07:48 +00:00
|
|
|
Handle<ByteArray> Factory::NewByteArray(int length, PretenureFlag pretenure) {
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_LE(0, length);
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateByteArray(length, pretenure),
|
|
|
|
ByteArray);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-27 11:11:09 +00:00
|
|
|
Handle<BytecodeArray> Factory::NewBytecodeArray(
|
|
|
|
int length, const byte* raw_bytecodes, int frame_size, int parameter_count,
|
|
|
|
Handle<FixedArray> constant_pool) {
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_LE(0, length);
|
2015-08-27 11:11:09 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->AllocateBytecodeArray(
|
|
|
|
length, raw_bytecodes, frame_size,
|
|
|
|
parameter_count, *constant_pool),
|
2015-07-24 12:02:41 +00:00
|
|
|
BytecodeArray);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-28 09:29:34 +00:00
|
|
|
Handle<FixedTypedArrayBase> Factory::NewFixedTypedArrayWithExternalPointer(
|
|
|
|
int length, ExternalArrayType array_type, void* external_pointer,
|
|
|
|
PretenureFlag pretenure) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(0 <= length && length <= Smi::kMaxValue);
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
2015-07-28 09:29:34 +00:00
|
|
|
isolate(), isolate()->heap()->AllocateFixedTypedArrayWithExternalPointer(
|
|
|
|
length, array_type, external_pointer, pretenure),
|
|
|
|
FixedTypedArrayBase);
|
2009-10-20 15:26:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-01-16 17:08:45 +00:00
|
|
|
Handle<FixedTypedArrayBase> Factory::NewFixedTypedArray(
|
2015-06-03 07:41:28 +00:00
|
|
|
int length, ExternalArrayType array_type, bool initialize,
|
2014-01-16 17:08:45 +00:00
|
|
|
PretenureFlag pretenure) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(0 <= length && length <= Smi::kMaxValue);
|
2015-06-03 07:41:28 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->AllocateFixedTypedArray(
|
|
|
|
length, array_type, initialize, pretenure),
|
|
|
|
FixedTypedArrayBase);
|
2014-01-16 17:08:45 +00:00
|
|
|
}
|
|
|
|
|
2013-06-12 15:03:44 +00:00
|
|
|
Handle<Cell> Factory::NewCell(Handle<Object> value) {
|
|
|
|
AllowDeferredHandleDereference convert_to_cell;
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateCell(*value),
|
|
|
|
Cell);
|
|
|
|
}
|
|
|
|
|
2017-02-10 15:19:19 +00:00
|
|
|
Handle<Cell> Factory::NewNoClosuresCell(Handle<Object> value) {
|
|
|
|
Handle<Cell> cell = NewCell(value);
|
|
|
|
cell->set_map_no_write_barrier(*no_closures_cell_map());
|
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<Cell> Factory::NewOneClosureCell(Handle<Object> value) {
|
|
|
|
Handle<Cell> cell = NewCell(value);
|
|
|
|
cell->set_map_no_write_barrier(*one_closure_cell_map());
|
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<Cell> Factory::NewManyClosuresCell(Handle<Object> value) {
|
|
|
|
Handle<Cell> cell = NewCell(value);
|
|
|
|
cell->set_map_no_write_barrier(*many_closures_cell_map());
|
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
|
2017-06-27 11:57:13 +00:00
|
|
|
Handle<PropertyCell> Factory::NewPropertyCell(Handle<Name> name) {
|
|
|
|
CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->AllocatePropertyCell(*name),
|
|
|
|
PropertyCell);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-14 14:43:45 +00:00
|
|
|
Handle<WeakCell> Factory::NewWeakCell(Handle<HeapObject> value) {
|
2015-04-29 08:36:05 +00:00
|
|
|
// It is safe to dereference the value because we are embedding it
|
|
|
|
// in cell and not inspecting its fields.
|
2014-10-14 14:43:45 +00:00
|
|
|
AllowDeferredHandleDereference convert_to_cell;
|
|
|
|
CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->AllocateWeakCell(*value),
|
|
|
|
WeakCell);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-03 13:18:19 +00:00
|
|
|
Handle<TransitionArray> Factory::NewTransitionArray(int capacity) {
|
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
|
|
|
isolate()->heap()->AllocateTransitionArray(capacity),
|
|
|
|
TransitionArray);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-08 10:02:16 +00:00
|
|
|
Handle<AllocationSite> Factory::NewAllocationSite() {
|
2014-04-16 12:54:29 +00:00
|
|
|
Handle<Map> map = allocation_site_map();
|
2015-04-07 11:31:57 +00:00
|
|
|
Handle<AllocationSite> site = New<AllocationSite>(map, OLD_SPACE);
|
2014-04-16 12:54:29 +00:00
|
|
|
site->Initialize();
|
|
|
|
|
|
|
|
// Link the site
|
|
|
|
site->set_weak_next(isolate()->heap()->allocation_sites_list());
|
|
|
|
isolate()->heap()->set_allocation_sites_list(*site);
|
|
|
|
return site;
|
2013-07-08 10:02:16 +00:00
|
|
|
}
|
|
|
|
|
2017-10-18 20:14:09 +00:00
|
|
|
Handle<Map> Factory::NewMap(InstanceType type, int instance_size,
|
|
|
|
ElementsKind elements_kind,
|
|
|
|
int inobject_properties) {
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
2017-10-18 20:14:09 +00:00
|
|
|
isolate()->heap()->AllocateMap(type, instance_size, elements_kind,
|
|
|
|
inobject_properties),
|
2011-03-18 20:35:07 +00:00
|
|
|
Map);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-29 07:02:11 +00:00
|
|
|
Handle<JSObject> Factory::CopyJSObject(Handle<JSObject> object) {
|
2017-10-13 16:33:03 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(), isolate()->heap()->CopyJSObject(*object, nullptr), JSObject);
|
2014-04-29 07:02:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<JSObject> Factory::CopyJSObjectWithAllocationSite(
|
|
|
|
Handle<JSObject> object,
|
|
|
|
Handle<AllocationSite> site) {
|
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
|
|
|
isolate()->heap()->CopyJSObject(
|
2017-10-13 16:33:03 +00:00
|
|
|
*object, site.is_null() ? nullptr : *site),
|
2014-04-29 07:02:11 +00:00
|
|
|
JSObject);
|
|
|
|
}
|
|
|
|
|
2014-04-28 15:33:16 +00:00
|
|
|
Handle<FixedArray> Factory::CopyFixedArrayWithMap(Handle<FixedArray> array,
|
|
|
|
Handle<Map> map) {
|
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
|
|
|
isolate()->heap()->CopyFixedArrayWithMap(*array, *map),
|
|
|
|
FixedArray);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2015-08-04 17:48:42 +00:00
|
|
|
Handle<FixedArray> Factory::CopyFixedArrayAndGrow(Handle<FixedArray> array,
|
2015-08-05 08:53:17 +00:00
|
|
|
int grow_by,
|
|
|
|
PretenureFlag pretenure) {
|
2017-07-11 20:56:40 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->CopyArrayAndGrow(*array, grow_by, pretenure),
|
|
|
|
FixedArray);
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<PropertyArray> Factory::CopyPropertyArrayAndGrow(
|
|
|
|
Handle<PropertyArray> array, int grow_by, PretenureFlag pretenure) {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->CopyArrayAndGrow(*array, grow_by, pretenure),
|
|
|
|
PropertyArray);
|
2015-08-04 17:48:42 +00:00
|
|
|
}
|
|
|
|
|
2016-02-11 18:58:49 +00:00
|
|
|
Handle<FixedArray> Factory::CopyFixedArrayUpTo(Handle<FixedArray> array,
|
|
|
|
int new_len,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->CopyFixedArrayUpTo(
|
|
|
|
*array, new_len, pretenure),
|
|
|
|
FixedArray);
|
|
|
|
}
|
2015-08-04 17:48:42 +00:00
|
|
|
|
2014-04-28 15:33:16 +00:00
|
|
|
Handle<FixedArray> Factory::CopyFixedArray(Handle<FixedArray> array) {
|
2014-03-17 13:42:37 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
2014-04-28 15:33:16 +00:00
|
|
|
isolate()->heap()->CopyFixedArray(*array),
|
2014-03-17 13:42:37 +00:00
|
|
|
FixedArray);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-28 15:33:16 +00:00
|
|
|
Handle<FixedArray> Factory::CopyAndTenureFixedCOWArray(
|
|
|
|
Handle<FixedArray> array) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(isolate()->heap()->InNewSpace(*array));
|
2013-10-04 07:25:24 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
2014-04-28 15:33:16 +00:00
|
|
|
isolate()->heap()->CopyAndTenureFixedCOWArray(*array),
|
2013-10-04 07:25:24 +00:00
|
|
|
FixedArray);
|
2012-11-13 12:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-19 11:36:55 +00:00
|
|
|
Handle<FixedDoubleArray> Factory::CopyFixedDoubleArray(
|
|
|
|
Handle<FixedDoubleArray> array) {
|
2014-04-28 15:33:16 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
|
|
|
isolate()->heap()->CopyFixedDoubleArray(*array),
|
|
|
|
FixedDoubleArray);
|
2011-10-19 11:36:55 +00:00
|
|
|
}
|
|
|
|
|
2017-07-27 12:45:00 +00:00
|
|
|
Handle<FeedbackVector> Factory::CopyFeedbackVector(
|
|
|
|
Handle<FeedbackVector> array) {
|
|
|
|
CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->CopyFeedbackVector(*array),
|
|
|
|
FeedbackVector);
|
|
|
|
}
|
2011-10-19 11:36:55 +00:00
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
Handle<Object> Factory::NewNumber(double value,
|
|
|
|
PretenureFlag pretenure) {
|
2016-07-21 09:18:47 +00:00
|
|
|
// Materialize as a SMI if possible
|
|
|
|
int32_t int_value;
|
|
|
|
if (DoubleToSmiInteger(value, &int_value)) {
|
2014-04-16 14:04:54 +00:00
|
|
|
return handle(Smi::FromInt(int_value), isolate());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Materialize the value in the heap.
|
2014-07-01 15:02:31 +00:00
|
|
|
return NewHeapNumber(value, IMMUTABLE, pretenure);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-21 10:18:47 +00:00
|
|
|
Handle<Object> Factory::NewNumberFromInt(int32_t value,
|
|
|
|
PretenureFlag pretenure) {
|
2014-04-16 14:04:54 +00:00
|
|
|
if (Smi::IsValid(value)) return handle(Smi::FromInt(value), isolate());
|
2014-07-01 15:02:31 +00:00
|
|
|
// Bypass NewNumber to avoid various redundant checks.
|
|
|
|
return NewHeapNumber(FastI2D(value), IMMUTABLE, pretenure);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-21 10:18:47 +00:00
|
|
|
Handle<Object> Factory::NewNumberFromUint(uint32_t value,
|
2014-04-30 12:25:18 +00:00
|
|
|
PretenureFlag pretenure) {
|
|
|
|
int32_t int32v = static_cast<int32_t>(value);
|
|
|
|
if (int32v >= 0 && Smi::IsValid(int32v)) {
|
|
|
|
return handle(Smi::FromInt(int32v), isolate());
|
|
|
|
}
|
2014-07-01 15:02:31 +00:00
|
|
|
return NewHeapNumber(FastUI2D(value), IMMUTABLE, pretenure);
|
2009-03-10 08:10:50 +00:00
|
|
|
}
|
|
|
|
|
2017-01-23 18:18:48 +00:00
|
|
|
Handle<HeapNumber> Factory::NewHeapNumber(MutableMode mode,
|
2013-05-08 15:02:08 +00:00
|
|
|
PretenureFlag pretenure) {
|
2017-01-23 18:18:48 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
|
|
|
isolate()->heap()->AllocateHeapNumber(mode, pretenure),
|
|
|
|
HeapNumber);
|
2013-05-08 15:02:08 +00:00
|
|
|
}
|
|
|
|
|
2017-09-13 21:31:59 +00:00
|
|
|
Handle<BigInt> Factory::NewBigInt(int length, PretenureFlag pretenure) {
|
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
|
|
|
isolate()->heap()->AllocateBigInt(length, true, pretenure),
|
2017-09-11 13:16:27 +00:00
|
|
|
BigInt);
|
|
|
|
}
|
|
|
|
|
2017-09-13 21:31:59 +00:00
|
|
|
Handle<BigInt> Factory::NewBigIntRaw(int length, PretenureFlag pretenure) {
|
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(), isolate()->heap()->AllocateBigInt(length, false, pretenure),
|
|
|
|
BigInt);
|
|
|
|
}
|
|
|
|
|
2017-10-27 06:11:55 +00:00
|
|
|
Handle<BigInt> Factory::NewBigIntFromSafeInteger(double value,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
if (value == 0) return NewBigInt(0);
|
|
|
|
|
|
|
|
uint64_t absolute = std::abs(value);
|
|
|
|
|
|
|
|
#if V8_TARGET_ARCH_64_BIT
|
|
|
|
static_assert(sizeof(BigInt::digit_t) == sizeof(uint64_t),
|
|
|
|
"unexpected BigInt digit size");
|
|
|
|
Handle<BigInt> result = NewBigIntRaw(1);
|
|
|
|
result->set_digit(0, absolute);
|
|
|
|
#else
|
|
|
|
static_assert(sizeof(BigInt::digit_t) == sizeof(uint32_t),
|
|
|
|
"unexpected BigInt digit size");
|
|
|
|
Handle<BigInt> result = NewBigIntRaw(2);
|
|
|
|
result->set_digit(0, absolute);
|
|
|
|
result->set_digit(1, absolute >> 32);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
result->set_sign(value < 0); // Treats -0 like 0.
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-10-10 09:00:16 +00:00
|
|
|
Handle<BigInt> Factory::NewBigIntFromInt(int value, PretenureFlag pretenure) {
|
|
|
|
if (value == 0) return NewBigInt(0);
|
|
|
|
Handle<BigInt> result = NewBigIntRaw(1);
|
|
|
|
if (value > 0) {
|
|
|
|
result->set_digit(0, value);
|
|
|
|
} else if (value == kMinInt) {
|
|
|
|
STATIC_ASSERT(kMinInt == -kMaxInt - 1);
|
|
|
|
result->set_digit(0, static_cast<BigInt::digit_t>(kMaxInt) + 1);
|
|
|
|
result->set_sign(true);
|
|
|
|
} else {
|
|
|
|
result->set_digit(0, -value);
|
|
|
|
result->set_sign(true);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-08-17 11:02:31 +00:00
|
|
|
Handle<Object> Factory::NewError(Handle<JSFunction> constructor,
|
2015-04-16 07:01:20 +00:00
|
|
|
MessageTemplate::Template template_index,
|
|
|
|
Handle<Object> arg0, Handle<Object> arg1,
|
|
|
|
Handle<Object> arg2) {
|
|
|
|
HandleScope scope(isolate());
|
2015-06-10 17:42:01 +00:00
|
|
|
if (isolate()->bootstrapper()->IsActive()) {
|
2015-08-17 11:02:31 +00:00
|
|
|
// During bootstrapping we cannot construct error objects.
|
|
|
|
return scope.CloseAndEscape(NewStringFromAsciiChecked(
|
|
|
|
MessageTemplate::TemplateString(template_index)));
|
2015-06-10 17:42:01 +00:00
|
|
|
}
|
2015-04-16 07:01:20 +00:00
|
|
|
|
|
|
|
if (arg0.is_null()) arg0 = undefined_value();
|
|
|
|
if (arg1.is_null()) arg1 = undefined_value();
|
|
|
|
if (arg2.is_null()) arg2 = undefined_value();
|
|
|
|
|
|
|
|
Handle<Object> result;
|
2016-08-03 12:20:39 +00:00
|
|
|
if (!ErrorUtils::MakeGenericError(isolate(), constructor, template_index,
|
|
|
|
arg0, arg1, arg2, SKIP_NONE)
|
2015-08-17 11:02:31 +00:00
|
|
|
.ToHandle(&result)) {
|
2016-08-03 12:20:39 +00:00
|
|
|
// If an exception is thrown while
|
|
|
|
// running the factory method, use the exception as the result.
|
|
|
|
DCHECK(isolate()->has_pending_exception());
|
|
|
|
result = handle(isolate()->pending_exception(), isolate());
|
|
|
|
isolate()->clear_pending_exception();
|
2015-04-16 07:01:20 +00:00
|
|
|
}
|
2016-08-03 12:20:39 +00:00
|
|
|
|
2015-04-16 07:01:20 +00:00
|
|
|
return scope.CloseAndEscape(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-14 15:12:34 +00:00
|
|
|
Handle<Object> Factory::NewError(Handle<JSFunction> constructor,
|
2015-02-24 09:01:33 +00:00
|
|
|
Handle<String> message) {
|
2016-08-03 13:56:49 +00:00
|
|
|
// Construct a new error object. If an exception is thrown, use the exception
|
|
|
|
// as the result.
|
|
|
|
|
|
|
|
Handle<Object> no_caller;
|
|
|
|
MaybeHandle<Object> maybe_error =
|
|
|
|
ErrorUtils::Construct(isolate(), constructor, constructor, message,
|
|
|
|
SKIP_NONE, no_caller, false);
|
|
|
|
if (maybe_error.is_null()) {
|
|
|
|
DCHECK(isolate()->has_pending_exception());
|
|
|
|
maybe_error = handle(isolate()->pending_exception(), isolate());
|
|
|
|
isolate()->clear_pending_exception();
|
2014-04-11 10:41:09 +00:00
|
|
|
}
|
2016-08-03 13:56:49 +00:00
|
|
|
|
|
|
|
return maybe_error.ToHandleChecked();
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2016-09-20 05:58:39 +00:00
|
|
|
Handle<Object> Factory::NewInvalidStringLengthError() {
|
2017-07-31 12:12:01 +00:00
|
|
|
if (FLAG_abort_on_stack_or_string_length_overflow) {
|
|
|
|
FATAL("Aborting on invalid string length");
|
|
|
|
}
|
2016-09-20 05:58:39 +00:00
|
|
|
// Invalidate the "string length" protector.
|
|
|
|
if (isolate()->IsStringLengthOverflowIntact()) {
|
|
|
|
isolate()->InvalidateStringLengthOverflowProtector();
|
|
|
|
}
|
|
|
|
return NewRangeError(MessageTemplate::kInvalidStringLength);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2015-09-01 09:25:19 +00:00
|
|
|
#define DEFINE_ERROR(NAME, name) \
|
|
|
|
Handle<Object> Factory::New##NAME(MessageTemplate::Template template_index, \
|
|
|
|
Handle<Object> arg0, Handle<Object> arg1, \
|
|
|
|
Handle<Object> arg2) { \
|
|
|
|
return NewError(isolate()->name##_function(), template_index, arg0, arg1, \
|
|
|
|
arg2); \
|
|
|
|
}
|
|
|
|
DEFINE_ERROR(Error, error)
|
|
|
|
DEFINE_ERROR(EvalError, eval_error)
|
|
|
|
DEFINE_ERROR(RangeError, range_error)
|
|
|
|
DEFINE_ERROR(ReferenceError, reference_error)
|
|
|
|
DEFINE_ERROR(SyntaxError, syntax_error)
|
|
|
|
DEFINE_ERROR(TypeError, type_error)
|
2016-10-13 16:17:44 +00:00
|
|
|
DEFINE_ERROR(WasmCompileError, wasm_compile_error)
|
2016-12-16 14:23:35 +00:00
|
|
|
DEFINE_ERROR(WasmLinkError, wasm_link_error)
|
2016-10-13 16:17:44 +00:00
|
|
|
DEFINE_ERROR(WasmRuntimeError, wasm_runtime_error)
|
2015-09-01 09:25:19 +00:00
|
|
|
#undef DEFINE_ERROR
|
|
|
|
|
2015-11-25 12:41:35 +00:00
|
|
|
Handle<JSFunction> Factory::NewFunction(Handle<Map> map,
|
|
|
|
Handle<SharedFunctionInfo> info,
|
2016-07-07 19:37:05 +00:00
|
|
|
Handle<Object> context_or_undefined,
|
2015-11-25 12:41:35 +00:00
|
|
|
PretenureFlag pretenure) {
|
|
|
|
AllocationSpace space = pretenure == TENURED ? OLD_SPACE : NEW_SPACE;
|
|
|
|
Handle<JSFunction> function = New<JSFunction>(map, space);
|
2016-07-07 19:37:05 +00:00
|
|
|
DCHECK(context_or_undefined->IsContext() ||
|
|
|
|
context_or_undefined->IsUndefined(isolate()));
|
2015-11-25 12:41:35 +00:00
|
|
|
|
2014-05-06 11:26:35 +00:00
|
|
|
function->initialize_properties();
|
|
|
|
function->initialize_elements();
|
|
|
|
function->set_shared(*info);
|
|
|
|
function->set_code(info->code());
|
2016-07-07 19:37:05 +00:00
|
|
|
function->set_context(*context_or_undefined);
|
2017-02-06 10:18:05 +00:00
|
|
|
function->set_feedback_vector_cell(*undefined_cell());
|
2017-10-12 15:37:46 +00:00
|
|
|
int header_size;
|
|
|
|
if (map->has_prototype_slot()) {
|
|
|
|
header_size = JSFunction::kSizeWithPrototype;
|
|
|
|
function->set_prototype_or_initial_map(*the_hole_value());
|
|
|
|
} else {
|
|
|
|
header_size = JSFunction::kSizeWithoutPrototype;
|
|
|
|
}
|
|
|
|
isolate()->heap()->InitializeJSObjectBody(*function, *map, header_size);
|
2015-11-25 12:41:35 +00:00
|
|
|
return function;
|
2014-05-06 11:26:35 +00:00
|
|
|
}
|
|
|
|
|
2017-11-08 12:56:08 +00:00
|
|
|
Handle<JSFunction> Factory::NewFunctionForTest(Handle<String> name) {
|
|
|
|
NewFunctionArgs args = NewFunctionArgs::ForFunctionWithoutCode(
|
|
|
|
name, isolate()->sloppy_function_map(), LanguageMode::kSloppy);
|
|
|
|
Handle<JSFunction> result = NewFunction(args);
|
|
|
|
DCHECK(is_sloppy(result->shared()->language_mode()));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<JSFunction> Factory::NewFunction(const NewFunctionArgs& args) {
|
|
|
|
DCHECK(!args.name_.is_null());
|
|
|
|
|
|
|
|
// Create the SharedFunctionInfo.
|
2014-07-01 12:12:34 +00:00
|
|
|
Handle<Context> context(isolate()->native_context());
|
2017-11-08 12:56:08 +00:00
|
|
|
Handle<Map> map = args.GetMap(isolate());
|
2015-11-24 17:16:40 +00:00
|
|
|
Handle<SharedFunctionInfo> info =
|
2017-11-08 12:56:08 +00:00
|
|
|
NewSharedFunctionInfo(args.name_, args.maybe_code_, map->is_constructor(),
|
|
|
|
kNormalFunction, args.maybe_builtin_id_);
|
|
|
|
|
|
|
|
// Proper language mode in shared function info will be set later.
|
2015-12-08 16:04:08 +00:00
|
|
|
DCHECK(is_sloppy(info->language_mode()));
|
2016-06-06 12:58:10 +00:00
|
|
|
DCHECK(!map->IsUndefined(isolate()));
|
2017-11-08 12:56:08 +00:00
|
|
|
|
2017-07-03 13:40:13 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
if (isolate()->bootstrapper()->IsActive()) {
|
|
|
|
Handle<Code> code;
|
2017-11-08 12:56:08 +00:00
|
|
|
bool has_code = args.maybe_code_.ToHandle(&code);
|
2017-07-03 13:40:13 +00:00
|
|
|
DCHECK(
|
|
|
|
// During bootstrapping some of these maps could be not created yet.
|
|
|
|
(*map == context->get(Context::STRICT_FUNCTION_MAP_INDEX)) ||
|
|
|
|
(*map ==
|
|
|
|
context->get(Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX)) ||
|
|
|
|
(*map ==
|
|
|
|
context->get(
|
|
|
|
Context::STRICT_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX)) ||
|
|
|
|
// Check if it's a creation of an empty or Proxy function during
|
|
|
|
// bootstrapping.
|
|
|
|
(has_code && (code->builtin_index() == Builtins::kEmptyFunction ||
|
|
|
|
code->builtin_index() == Builtins::kProxyConstructor)));
|
|
|
|
} else {
|
|
|
|
DCHECK(
|
|
|
|
(*map == *isolate()->sloppy_function_map()) ||
|
|
|
|
(*map == *isolate()->sloppy_function_without_prototype_map()) ||
|
|
|
|
(*map == *isolate()->sloppy_function_with_readonly_prototype_map()) ||
|
|
|
|
(*map == *isolate()->strict_function_map()) ||
|
|
|
|
(*map == *isolate()->strict_function_without_prototype_map()) ||
|
|
|
|
(*map == *isolate()->native_function_map()));
|
|
|
|
}
|
|
|
|
#endif
|
2014-05-06 11:26:35 +00:00
|
|
|
|
2017-11-08 12:56:08 +00:00
|
|
|
Handle<JSFunction> result = NewFunction(map, info, context);
|
2014-05-06 11:26:35 +00:00
|
|
|
|
2017-11-08 12:56:08 +00:00
|
|
|
if (args.should_set_prototype_) {
|
|
|
|
result->set_prototype_or_initial_map(
|
|
|
|
*args.maybe_prototype_.ToHandleChecked());
|
|
|
|
}
|
2014-05-09 17:39:54 +00:00
|
|
|
|
2017-11-08 12:56:08 +00:00
|
|
|
if (args.should_set_language_mode_) {
|
|
|
|
result->shared()->set_language_mode(args.language_mode_);
|
2017-07-07 09:24:57 +00:00
|
|
|
}
|
2016-06-27 18:03:59 +00:00
|
|
|
|
2017-11-08 12:56:08 +00:00
|
|
|
if (args.should_create_and_set_initial_map_) {
|
|
|
|
ElementsKind elements_kind;
|
|
|
|
switch (args.type_) {
|
|
|
|
case JS_ARRAY_TYPE:
|
|
|
|
elements_kind = PACKED_SMI_ELEMENTS;
|
|
|
|
break;
|
|
|
|
case JS_ARGUMENTS_TYPE:
|
|
|
|
elements_kind = PACKED_ELEMENTS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
elements_kind = TERMINAL_FAST_ELEMENTS_KIND;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Handle<Map> initial_map = NewMap(args.type_, args.instance_size_,
|
|
|
|
elements_kind, args.inobject_properties_);
|
|
|
|
// TODO(littledan): Why do we have this is_generator test when
|
|
|
|
// NewFunctionPrototype already handles finding an appropriately
|
|
|
|
// shared prototype?
|
|
|
|
Handle<Object> prototype = args.maybe_prototype_.ToHandleChecked();
|
|
|
|
if (!IsResumableFunction(result->shared()->kind())) {
|
|
|
|
if (prototype->IsTheHole(isolate())) {
|
|
|
|
prototype = NewFunctionPrototype(result);
|
|
|
|
}
|
2016-06-27 18:03:59 +00:00
|
|
|
}
|
2017-11-08 12:56:08 +00:00
|
|
|
JSFunction::SetInitialMap(result, initial_map, prototype);
|
2016-06-27 18:03:59 +00:00
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2017-11-08 12:56:08 +00:00
|
|
|
return result;
|
2014-04-29 17:48:07 +00:00
|
|
|
}
|
|
|
|
|
2014-05-06 11:26:35 +00:00
|
|
|
Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
|
|
|
|
// Make sure to use globals from the function's context, since the function
|
|
|
|
// can be from a different context.
|
|
|
|
Handle<Context> native_context(function->context()->native_context());
|
|
|
|
Handle<Map> new_map;
|
[async-iteration] implement AsyncGenerator
- Introduce new struct AsyncGeneratorRequest, which holds
information pertinent to resuming execution of an
AsyncGenerator, such as the Promise associated with the async
generator request. It is intended to be used as a singly
linked list, and holds a pointer to the next item in te queue.
- Introduce JSAsyncGeneratorObject (subclass of
JSGeneratorObject), which includes several new internal fields
(`queue` which contains a singly linked list of
AsyncGeneratorRequest objects, and `await_input` which
contains the sent value from an Await expression (This is
necessary to prevent function.sent (used by yield*) from
having the sent value observably overwritten during
execution).
- Modify SuspendGenerator to accept a set of Flags, which
indicate whether the suspend is for a Yield or Await, and
whether it takes place on an async generator or ES6
generator.
- Introduce interpreter intrinsics and TF intrinsic lowering for
accessing the await input of an async generator
- Modify the JSGeneratorStore operator to understand whether or
not it's suspending for a normal yield, or an AsyncGenerator
Await. This ensures appropriate registers are stored.
- Add versions of ResumeGeneratorTrampoline which store the
input value in a different field depending on wether it's an
AsyncGenerator Await resume, or an ordinary resume. Also modifies
whether debug code will assert that the generator object is a
JSGeneratorObject or a JSAsyncGeneratorObject depending on the
resume type.
BUG=v8:5855
R=bmeurer@chromium.org, rmcilroy@chromium.org, jgruber@chromium.org,
littledan@chromium.org, neis@chromium.org
TBR=marja@chromium.org
Change-Id: I9d58df1d344465fc937fe7eed322424204497187
Reviewed-on: https://chromium-review.googlesource.com/446961
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44240}
2017-03-29 13:41:45 +00:00
|
|
|
if (V8_UNLIKELY(IsAsyncGeneratorFunction(function->shared()->kind()))) {
|
|
|
|
new_map = handle(native_context->async_generator_object_prototype_map());
|
|
|
|
} else if (IsResumableFunction(function->shared()->kind())) {
|
2016-05-31 17:13:58 +00:00
|
|
|
// Generator and async function prototypes can share maps since they
|
|
|
|
// don't have "constructor" properties.
|
2014-05-06 11:26:35 +00:00
|
|
|
new_map = handle(native_context->generator_object_prototype_map());
|
|
|
|
} else {
|
|
|
|
// Each function prototype gets a fresh map to avoid unwanted sharing of
|
|
|
|
// maps between prototypes of different constructors.
|
|
|
|
Handle<JSFunction> object_function(native_context->object_function());
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(object_function->has_initial_map());
|
2014-08-07 16:14:22 +00:00
|
|
|
new_map = handle(object_function->initial_map());
|
2014-05-06 11:26:35 +00:00
|
|
|
}
|
|
|
|
|
2014-08-11 14:00:58 +00:00
|
|
|
DCHECK(!new_map->is_prototype_map());
|
2014-05-06 11:26:35 +00:00
|
|
|
Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
|
|
|
|
|
2016-09-28 21:23:53 +00:00
|
|
|
if (!IsResumableFunction(function->shared()->kind())) {
|
2014-06-30 13:48:57 +00:00
|
|
|
JSObject::AddProperty(prototype, constructor_string(), function, DONT_ENUM);
|
2014-05-06 11:26:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return prototype;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
|
|
|
|
Handle<SharedFunctionInfo> info,
|
|
|
|
Handle<Context> context,
|
|
|
|
PretenureFlag pretenure) {
|
2017-06-12 15:47:14 +00:00
|
|
|
Handle<Map> initial_map(
|
|
|
|
Map::cast(context->native_context()->get(info->function_map_index())));
|
2015-11-03 16:42:21 +00:00
|
|
|
return NewFunctionFromSharedFunctionInfo(initial_map, info, context,
|
|
|
|
pretenure);
|
|
|
|
}
|
|
|
|
|
2017-01-09 15:31:00 +00:00
|
|
|
Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
|
|
|
|
Handle<SharedFunctionInfo> info, Handle<Context> context,
|
2017-02-06 10:18:05 +00:00
|
|
|
Handle<Cell> vector, PretenureFlag pretenure) {
|
2017-06-12 15:47:14 +00:00
|
|
|
Handle<Map> initial_map(
|
|
|
|
Map::cast(context->native_context()->get(info->function_map_index())));
|
2017-01-30 12:31:35 +00:00
|
|
|
return NewFunctionFromSharedFunctionInfo(initial_map, info, context, vector,
|
2017-01-09 15:31:00 +00:00
|
|
|
pretenure);
|
|
|
|
}
|
|
|
|
|
2015-11-03 16:42:21 +00:00
|
|
|
Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
|
|
|
|
Handle<Map> initial_map, Handle<SharedFunctionInfo> info,
|
2016-07-07 19:37:05 +00:00
|
|
|
Handle<Object> context_or_undefined, PretenureFlag pretenure) {
|
2015-11-03 16:42:21 +00:00
|
|
|
DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
|
|
|
|
Handle<JSFunction> result =
|
2016-07-07 19:37:05 +00:00
|
|
|
NewFunction(initial_map, info, context_or_undefined, pretenure);
|
2014-05-06 11:26:35 +00:00
|
|
|
|
2016-07-07 19:37:05 +00:00
|
|
|
if (context_or_undefined->IsContext()) {
|
|
|
|
// Give compiler a chance to pre-initialize.
|
|
|
|
Compiler::PostInstantiation(result, pretenure);
|
|
|
|
}
|
2014-05-06 11:26:35 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-01-09 15:31:00 +00:00
|
|
|
Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
|
|
|
|
Handle<Map> initial_map, Handle<SharedFunctionInfo> info,
|
2017-02-06 10:18:05 +00:00
|
|
|
Handle<Object> context_or_undefined, Handle<Cell> vector,
|
2017-01-09 15:31:00 +00:00
|
|
|
PretenureFlag pretenure) {
|
|
|
|
DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
|
|
|
|
Handle<JSFunction> result =
|
|
|
|
NewFunction(initial_map, info, context_or_undefined, pretenure);
|
|
|
|
|
2017-02-10 15:19:19 +00:00
|
|
|
// Bump the closure count that is encoded in the vector cell's map.
|
|
|
|
if (vector->map() == *no_closures_cell_map()) {
|
|
|
|
vector->set_map(*one_closure_cell_map());
|
|
|
|
} else if (vector->map() == *one_closure_cell_map()) {
|
|
|
|
vector->set_map(*many_closures_cell_map());
|
|
|
|
} else {
|
|
|
|
DCHECK_EQ(vector->map(), *many_closures_cell_map());
|
|
|
|
}
|
|
|
|
|
2017-05-09 21:45:33 +00:00
|
|
|
// Check that the optimized code in the feedback vector wasn't marked for
|
|
|
|
// deoptimization while not pointed to by any live JSFunction.
|
|
|
|
if (vector->value()->IsFeedbackVector()) {
|
|
|
|
FeedbackVector::cast(vector->value())
|
|
|
|
->EvictOptimizedCodeMarkedForDeoptimization(
|
|
|
|
*info, "new function from shared function info");
|
|
|
|
}
|
2017-02-06 10:18:05 +00:00
|
|
|
result->set_feedback_vector_cell(*vector);
|
2017-01-09 15:31:00 +00:00
|
|
|
|
|
|
|
if (context_or_undefined->IsContext()) {
|
|
|
|
// Give compiler a chance to pre-initialize.
|
|
|
|
Compiler::PostInstantiation(result, pretenure);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2014-05-06 11:26:35 +00:00
|
|
|
|
2011-11-03 10:36:55 +00:00
|
|
|
Handle<ScopeInfo> Factory::NewScopeInfo(int length) {
|
2014-04-07 10:12:54 +00:00
|
|
|
Handle<FixedArray> array = NewFixedArray(length, TENURED);
|
|
|
|
array->set_map_no_write_barrier(*scope_info_map());
|
|
|
|
Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(array);
|
|
|
|
return scope_info;
|
2011-08-11 16:29:28 +00:00
|
|
|
}
|
|
|
|
|
2016-08-31 14:25:28 +00:00
|
|
|
Handle<ModuleInfo> Factory::NewModuleInfo() {
|
|
|
|
Handle<FixedArray> array = NewFixedArray(ModuleInfo::kLength, TENURED);
|
|
|
|
array->set_map_no_write_barrier(*module_info_map());
|
2016-09-12 12:54:47 +00:00
|
|
|
return Handle<ModuleInfo>::cast(array);
|
2016-08-31 14:25:28 +00:00
|
|
|
}
|
2011-08-11 16:29:28 +00:00
|
|
|
|
2017-06-30 10:38:38 +00:00
|
|
|
Handle<PreParsedScopeData> Factory::NewPreParsedScopeData() {
|
|
|
|
Handle<PreParsedScopeData> result =
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<PreParsedScopeData>::cast(NewStruct(TUPLE2_TYPE, TENURED));
|
2017-09-29 12:58:14 +00:00
|
|
|
result->set_scope_data(PodArray<uint8_t>::cast(*empty_byte_array()));
|
2017-06-30 10:38:38 +00:00
|
|
|
result->set_child_data(*empty_fixed_array());
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-11-13 12:27:03 +00:00
|
|
|
Handle<JSObject> Factory::NewExternal(void* value) {
|
2014-04-07 10:12:54 +00:00
|
|
|
Handle<Foreign> foreign = NewForeign(static_cast<Address>(value));
|
|
|
|
Handle<JSObject> external = NewJSObjectFromMap(external_map());
|
2017-03-17 13:26:05 +00:00
|
|
|
external->SetEmbedderField(0, *foreign);
|
2014-04-07 10:12:54 +00:00
|
|
|
return external;
|
2012-11-13 12:27:03 +00:00
|
|
|
}
|
|
|
|
|
2017-10-25 09:51:05 +00:00
|
|
|
Handle<CodeDataContainer> Factory::NewCodeDataContainer(int flags) {
|
|
|
|
Handle<CodeDataContainer> data_container =
|
|
|
|
New<CodeDataContainer>(code_data_container_map(), OLD_SPACE);
|
2017-10-26 11:21:23 +00:00
|
|
|
data_container->set_next_code_link(*undefined_value(), SKIP_WRITE_BARRIER);
|
2017-10-25 09:51:05 +00:00
|
|
|
data_container->set_kind_specific_flags(flags);
|
|
|
|
data_container->clear_padding();
|
|
|
|
return data_container;
|
|
|
|
}
|
2012-11-13 12:27:03 +00:00
|
|
|
|
2014-04-29 13:58:55 +00:00
|
|
|
Handle<Code> Factory::NewCodeRaw(int object_size, bool immovable) {
|
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
|
|
|
isolate()->heap()->AllocateCode(object_size, immovable),
|
2014-04-16 11:38:56 +00:00
|
|
|
Code);
|
|
|
|
}
|
|
|
|
|
2017-10-19 14:42:43 +00:00
|
|
|
Handle<Code> Factory::NewCode(
|
|
|
|
const CodeDesc& desc, Code::Kind kind, Handle<Object> self_ref,
|
|
|
|
MaybeHandle<HandlerTable> maybe_handler_table,
|
|
|
|
MaybeHandle<ByteArray> maybe_source_position_table,
|
2017-10-25 13:46:39 +00:00
|
|
|
MaybeHandle<DeoptimizationData> maybe_deopt_data, bool immovable,
|
2017-10-26 13:00:43 +00:00
|
|
|
uint32_t stub_key, bool is_turbofanned, int stack_slots,
|
|
|
|
int safepoint_table_offset) {
|
2014-04-16 11:38:56 +00:00
|
|
|
Handle<ByteArray> reloc_info = NewByteArray(desc.reloc_size, TENURED);
|
2017-10-25 09:51:05 +00:00
|
|
|
Handle<CodeDataContainer> data_container = NewCodeDataContainer(0);
|
2014-04-16 11:38:56 +00:00
|
|
|
|
2017-10-17 15:00:20 +00:00
|
|
|
Handle<HandlerTable> handler_table =
|
|
|
|
maybe_handler_table.is_null() ? HandlerTable::Empty(isolate())
|
|
|
|
: maybe_handler_table.ToHandleChecked();
|
2017-10-19 14:42:43 +00:00
|
|
|
Handle<ByteArray> source_position_table =
|
|
|
|
maybe_source_position_table.is_null()
|
|
|
|
? empty_byte_array()
|
|
|
|
: maybe_source_position_table.ToHandleChecked();
|
2017-10-18 12:50:14 +00:00
|
|
|
Handle<DeoptimizationData> deopt_data =
|
|
|
|
maybe_deopt_data.is_null() ? DeoptimizationData::Empty(isolate())
|
|
|
|
: maybe_deopt_data.ToHandleChecked();
|
2017-10-17 15:00:20 +00:00
|
|
|
|
2016-06-27 15:06:32 +00:00
|
|
|
bool has_unwinding_info = desc.unwinding_info != nullptr;
|
|
|
|
DCHECK((has_unwinding_info && desc.unwinding_info_size > 0) ||
|
|
|
|
(!has_unwinding_info && desc.unwinding_info_size == 0));
|
|
|
|
|
2014-04-16 11:38:56 +00:00
|
|
|
// Compute size.
|
2016-06-27 15:06:32 +00:00
|
|
|
int body_size = desc.instr_size;
|
|
|
|
int unwinding_info_size_field_size = kInt64Size;
|
|
|
|
if (has_unwinding_info) {
|
|
|
|
body_size = RoundUp(body_size, kInt64Size) + desc.unwinding_info_size +
|
|
|
|
unwinding_info_size_field_size;
|
|
|
|
}
|
|
|
|
int obj_size = Code::SizeFor(RoundUp(body_size, kObjectAlignment));
|
2014-04-16 11:38:56 +00:00
|
|
|
|
2017-10-20 07:13:43 +00:00
|
|
|
CodeSpaceMemoryModificationScope code_allocation(isolate()->heap());
|
2014-04-29 13:58:55 +00:00
|
|
|
Handle<Code> code = NewCodeRaw(obj_size, immovable);
|
2016-05-19 17:53:56 +00:00
|
|
|
DCHECK(!isolate()->heap()->memory_allocator()->code_range()->valid() ||
|
2016-04-06 11:38:31 +00:00
|
|
|
isolate()->heap()->memory_allocator()->code_range()->contains(
|
|
|
|
code->address()) ||
|
2015-06-12 11:42:06 +00:00
|
|
|
obj_size <= isolate()->heap()->code_space()->AreaSize());
|
2014-04-16 11:38:56 +00:00
|
|
|
|
|
|
|
// The code object has not been fully initialized yet. We rely on the
|
|
|
|
// fact that no allocation will happen from this point on.
|
|
|
|
DisallowHeapAllocation no_gc;
|
|
|
|
code->set_instruction_size(desc.instr_size);
|
|
|
|
code->set_relocation_info(*reloc_info);
|
2017-09-29 14:59:24 +00:00
|
|
|
code->initialize_flags(kind);
|
2016-06-27 15:06:32 +00:00
|
|
|
code->set_has_unwinding_info(has_unwinding_info);
|
2017-10-25 13:46:39 +00:00
|
|
|
code->set_is_turbofanned(is_turbofanned);
|
|
|
|
code->set_stack_slots(stack_slots);
|
|
|
|
code->set_safepoint_table_offset(safepoint_table_offset);
|
2017-10-25 09:51:05 +00:00
|
|
|
code->set_code_data_container(*data_container);
|
2017-03-17 07:27:39 +00:00
|
|
|
code->set_has_tagged_params(true);
|
2017-10-18 12:50:14 +00:00
|
|
|
code->set_deoptimization_data(*deopt_data);
|
2017-10-26 13:00:43 +00:00
|
|
|
code->set_stub_key(stub_key);
|
2017-10-17 15:00:20 +00:00
|
|
|
code->set_handler_table(*handler_table);
|
2017-10-19 14:42:43 +00:00
|
|
|
code->set_source_position_table(*source_position_table);
|
2017-10-25 20:14:44 +00:00
|
|
|
code->set_protected_instructions(*empty_fixed_array(), SKIP_WRITE_BARRIER);
|
2015-11-26 10:43:28 +00:00
|
|
|
code->set_constant_pool_offset(desc.instr_size - desc.constant_pool_size);
|
2016-08-18 14:34:03 +00:00
|
|
|
code->set_builtin_index(-1);
|
2017-03-13 22:12:23 +00:00
|
|
|
code->set_trap_handler_index(Smi::FromInt(-1));
|
2015-11-26 10:43:28 +00:00
|
|
|
|
2017-03-17 07:27:39 +00:00
|
|
|
switch (code->kind()) {
|
|
|
|
case Code::OPTIMIZED_FUNCTION:
|
|
|
|
code->set_marked_for_deoptimization(false);
|
|
|
|
break;
|
|
|
|
case Code::JS_TO_WASM_FUNCTION:
|
2017-11-08 12:27:46 +00:00
|
|
|
case Code::C_WASM_ENTRY:
|
2017-03-17 07:27:39 +00:00
|
|
|
case Code::WASM_FUNCTION:
|
|
|
|
code->set_has_tagged_params(false);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2014-04-16 11:38:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Allow self references to created code object by patching the handle to
|
|
|
|
// point to the newly allocated Code object.
|
|
|
|
if (!self_ref.is_null()) *(self_ref.location()) = *code;
|
|
|
|
|
|
|
|
// Migrate generated code.
|
|
|
|
// The generated code can contain Object** values (typically from handles)
|
|
|
|
// that are dereferenced during the copy to point directly to the actual heap
|
|
|
|
// objects. These pointers can include references to the code object itself,
|
|
|
|
// through the self_reference parameter.
|
|
|
|
code->CopyFrom(desc);
|
|
|
|
|
2017-08-02 13:05:45 +00:00
|
|
|
code->clear_padding();
|
|
|
|
|
2014-04-16 11:38:56 +00:00
|
|
|
#ifdef VERIFY_HEAP
|
2014-04-30 12:25:18 +00:00
|
|
|
if (FLAG_verify_heap) code->ObjectVerify();
|
2014-04-16 11:38:56 +00:00
|
|
|
#endif
|
|
|
|
return code;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2017-09-11 12:28:53 +00:00
|
|
|
Handle<Code> Factory::NewCodeForDeserialization(uint32_t size) {
|
|
|
|
const bool kNotImmovable = false;
|
|
|
|
return NewCodeRaw(size, kNotImmovable);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
Handle<Code> Factory::CopyCode(Handle<Code> code) {
|
2017-10-25 09:51:05 +00:00
|
|
|
Handle<CodeDataContainer> data_container =
|
|
|
|
NewCodeDataContainer(code->code_data_container()->kind_specific_flags());
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
2017-10-25 09:51:05 +00:00
|
|
|
isolate()->heap()->CopyCode(*code, *data_container), Code);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-22 13:16:46 +00:00
|
|
|
Handle<BytecodeArray> Factory::CopyBytecodeArray(
|
|
|
|
Handle<BytecodeArray> bytecode_array) {
|
|
|
|
CALL_HEAP_FUNCTION(isolate(),
|
|
|
|
isolate()->heap()->CopyBytecodeArray(*bytecode_array),
|
|
|
|
BytecodeArray);
|
|
|
|
}
|
2010-03-15 21:06:51 +00:00
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor,
|
|
|
|
PretenureFlag pretenure) {
|
2013-11-05 12:11:27 +00:00
|
|
|
JSFunction::EnsureHasInitialMap(constructor);
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateJSObject(*constructor, pretenure), JSObject);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 19:00:36 +00:00
|
|
|
Handle<JSObject> Factory::NewJSObjectWithNullProto(PretenureFlag pretenure) {
|
|
|
|
Handle<JSObject> result =
|
|
|
|
NewJSObject(isolate()->object_function(), pretenure);
|
2016-04-05 12:07:43 +00:00
|
|
|
Handle<Map> new_map =
|
|
|
|
Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto");
|
|
|
|
Map::SetPrototype(new_map, null_value());
|
|
|
|
JSObject::MigrateToMap(result, new_map);
|
|
|
|
return result;
|
|
|
|
}
|
2014-03-19 13:39:09 +00:00
|
|
|
|
2015-11-02 14:57:59 +00:00
|
|
|
Handle<JSGlobalObject> Factory::NewJSGlobalObject(
|
|
|
|
Handle<JSFunction> constructor) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(constructor->has_initial_map());
|
2013-10-21 13:55:24 +00:00
|
|
|
Handle<Map> map(constructor->initial_map());
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(map->is_dictionary_map());
|
2013-10-21 13:55:24 +00:00
|
|
|
|
|
|
|
// Make sure no field properties are described in the initial map.
|
|
|
|
// This guarantees us that normalizing the properties does not
|
|
|
|
// require us to change property values to PropertyCells.
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_EQ(map->NextFreePropertyIndex(), 0);
|
2013-10-21 13:55:24 +00:00
|
|
|
|
|
|
|
// Make sure we don't have a ton of pre-allocated slots in the
|
|
|
|
// global objects. They will be unused once we normalize the object.
|
2017-10-20 12:49:15 +00:00
|
|
|
DCHECK_EQ(map->UnusedPropertyFields(), 0);
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_EQ(map->GetInObjectProperties(), 0);
|
2013-10-21 13:55:24 +00:00
|
|
|
|
|
|
|
// Initial size of the backing store to avoid resize of the storage during
|
|
|
|
// bootstrapping. The size differs between the JS global object ad the
|
|
|
|
// builtins object.
|
2015-11-02 13:04:20 +00:00
|
|
|
int initial_size = 64;
|
2013-10-21 13:55:24 +00:00
|
|
|
|
|
|
|
// Allocate a dictionary object for backing storage.
|
|
|
|
int at_least_space_for = map->NumberOfOwnDescriptors() * 2 + initial_size;
|
2015-06-01 16:24:59 +00:00
|
|
|
Handle<GlobalDictionary> dictionary =
|
|
|
|
GlobalDictionary::New(isolate(), at_least_space_for);
|
2013-10-21 13:55:24 +00:00
|
|
|
|
|
|
|
// The global object might be created from an object template with accessors.
|
|
|
|
// Fill these accessors into the dictionary.
|
|
|
|
Handle<DescriptorArray> descs(map->instance_descriptors());
|
|
|
|
for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
|
|
|
|
PropertyDetails details = descs->GetDetails(i);
|
2015-01-19 17:49:13 +00:00
|
|
|
// Only accessors are expected.
|
2017-01-12 16:37:12 +00:00
|
|
|
DCHECK_EQ(kAccessor, details.kind());
|
2017-06-22 09:52:28 +00:00
|
|
|
PropertyDetails d(kAccessor, details.attributes(),
|
2015-03-17 13:27:25 +00:00
|
|
|
PropertyCellType::kMutable);
|
2013-10-21 13:55:24 +00:00
|
|
|
Handle<Name> name(descs->GetKey(i));
|
2017-06-27 11:57:13 +00:00
|
|
|
Handle<PropertyCell> cell = NewPropertyCell(name);
|
2017-01-13 13:23:27 +00:00
|
|
|
cell->set_value(descs->GetValue(i));
|
2014-04-24 15:45:44 +00:00
|
|
|
// |dictionary| already contains enough space for all properties.
|
2015-06-01 16:24:59 +00:00
|
|
|
USE(GlobalDictionary::Add(dictionary, name, cell, d));
|
2013-10-21 13:55:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate the global object and initialize it with the backing store.
|
2015-11-02 14:57:59 +00:00
|
|
|
Handle<JSGlobalObject> global = New<JSGlobalObject>(map, OLD_SPACE);
|
2013-10-21 13:55:24 +00:00
|
|
|
isolate()->heap()->InitializeJSObjectFromMap(*global, *dictionary, *map);
|
|
|
|
|
|
|
|
// Create a new map for the global object.
|
|
|
|
Handle<Map> new_map = Map::CopyDropDescriptors(map);
|
[builtins] Speed-up Object.prototype.toString.
The @@toStringTag lookup in Object.prototype.toString causes quite a
lot of overhead and oftentimes dominates the builtin performance. These
lookups are almost always negative, especially for primitive values,
and Object.prototype.toString is often used to implement predicates
(like in Node core or in AngularJS), so having a way to skip the
negative lookup yields big performance gains.
This CL introduces a "MayHaveInterestingSymbols" bit on every map,
which says whether instances with this map may have an interesting
symbol. Currently only @@toStringTag is considered an interesting
symbol, but we can extend that in the future.
In the Object.prototype.toString we can use the interesting symbols
bit to do a quick check on the prototype chain to see if there are
any maps that might have the @@toStringTag, and if not, we can just
immediately return the result, which is very fast because it's derived
from the instance type. This also avoids the ToObject conversions for
primitive values, which is important, since this causes unnecessary
GC traffic and in for example AngularJS, strings are also often probed
via the Object.prototype.toString based predicates.
This boosts Speedometer/AngularJS by over 3% and Speedometer overall
by up to 1%. On the microbenchmark from the similar SpiderMonkey bug
(https://bugzilla.mozilla.org/show_bug.cgi?id=1369042), we go from
roughly 450ms to 70ms, which corresponds to a 6.5x improvement.
```
function f() {
var res = "";
var a = [1, 2, 3];
var toString = Object.prototype.toString;
var t = new Date;
for (var i = 0; i < 5000000; i++)
res = toString.call(a);
print(new Date - t);
return res;
}
f();
```
The design document at https://goo.gl/e8CruQ has some additional
data points.
TBR=ulan@chromium.org
Bug: v8:6654
Change-Id: I31932cf41ecddad079d294e2c322a852af0ed244
Reviewed-on: https://chromium-review.googlesource.com/593620
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47034}
2017-08-01 08:11:14 +00:00
|
|
|
new_map->set_may_have_interesting_symbols(true);
|
2013-10-21 13:55:24 +00:00
|
|
|
new_map->set_dictionary_map(true);
|
|
|
|
|
|
|
|
// Set up the global object as a normalized object.
|
2017-07-11 20:56:40 +00:00
|
|
|
global->set_global_dictionary(*dictionary);
|
2017-06-09 10:06:11 +00:00
|
|
|
global->synchronized_set_map(*new_map);
|
2013-10-21 13:55:24 +00:00
|
|
|
|
|
|
|
// Make sure result is a global object with properties in dictionary.
|
2015-11-02 14:57:59 +00:00
|
|
|
DCHECK(global->IsJSGlobalObject() && !global->HasFastProperties());
|
2013-10-21 13:55:24 +00:00
|
|
|
return global;
|
|
|
|
}
|
|
|
|
|
2009-06-30 10:05:36 +00:00
|
|
|
|
2014-03-17 15:01:45 +00:00
|
|
|
Handle<JSObject> Factory::NewJSObjectFromMap(
|
|
|
|
Handle<Map> map,
|
|
|
|
PretenureFlag pretenure,
|
|
|
|
Handle<AllocationSite> allocation_site) {
|
2011-03-18 20:35:07 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
2014-03-17 15:01:45 +00:00
|
|
|
isolate()->heap()->AllocateJSObjectFromMap(
|
2017-10-13 16:33:03 +00:00
|
|
|
*map, pretenure,
|
|
|
|
allocation_site.is_null() ? nullptr : *allocation_site),
|
2011-03-18 20:35:07 +00:00
|
|
|
JSObject);
|
2008-09-25 07:46:07 +00:00
|
|
|
}
|
|
|
|
|
2017-04-27 14:48:32 +00:00
|
|
|
Handle<JSObject> Factory::NewSlowJSObjectFromMap(Handle<Map> map, int capacity,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
DCHECK(map->is_dictionary_map());
|
2017-07-11 20:56:40 +00:00
|
|
|
Handle<NameDictionary> object_properties =
|
2017-04-27 14:48:32 +00:00
|
|
|
NameDictionary::New(isolate(), capacity);
|
|
|
|
Handle<JSObject> js_object = NewJSObjectFromMap(map, pretenure);
|
2017-07-17 23:30:32 +00:00
|
|
|
js_object->set_raw_properties_or_hash(*object_properties);
|
2017-04-27 14:48:32 +00:00
|
|
|
return js_object;
|
|
|
|
}
|
2008-09-25 07:46:07 +00:00
|
|
|
|
2014-04-07 10:00:14 +00:00
|
|
|
Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind,
|
|
|
|
PretenureFlag pretenure) {
|
2017-07-19 13:39:05 +00:00
|
|
|
Context* native_context = isolate()->raw_native_context();
|
|
|
|
Map* map = native_context->GetInitialJSArrayMap(elements_kind);
|
2015-06-02 11:46:04 +00:00
|
|
|
if (map == nullptr) {
|
|
|
|
JSFunction* array_function = native_context->array_function();
|
|
|
|
map = array_function->initial_map();
|
|
|
|
}
|
2014-04-07 12:43:35 +00:00
|
|
|
return Handle<JSArray>::cast(NewJSObjectFromMap(handle(map), pretenure));
|
2014-04-07 10:00:14 +00:00
|
|
|
}
|
|
|
|
|
2015-06-02 11:46:04 +00:00
|
|
|
Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind, int length,
|
2016-03-01 16:05:38 +00:00
|
|
|
int capacity,
|
2014-03-27 16:41:09 +00:00
|
|
|
ArrayStorageAllocationMode mode,
|
2008-07-03 15:10:15 +00:00
|
|
|
PretenureFlag pretenure) {
|
2016-03-01 16:05:38 +00:00
|
|
|
Handle<JSArray> array = NewJSArray(elements_kind, pretenure);
|
2014-04-07 12:43:35 +00:00
|
|
|
NewJSArrayStorage(array, length, capacity, mode);
|
|
|
|
return array;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
2011-12-09 08:50:19 +00:00
|
|
|
Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArrayBase> elements,
|
2012-01-26 21:47:57 +00:00
|
|
|
ElementsKind elements_kind,
|
2016-03-01 16:05:38 +00:00
|
|
|
int length,
|
2008-07-03 15:10:15 +00:00
|
|
|
PretenureFlag pretenure) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(length <= elements->length());
|
2016-03-01 16:05:38 +00:00
|
|
|
Handle<JSArray> array = NewJSArray(elements_kind, pretenure);
|
2014-04-07 10:00:14 +00:00
|
|
|
|
|
|
|
array->set_elements(*elements);
|
|
|
|
array->set_length(Smi::FromInt(length));
|
2017-07-06 08:26:19 +00:00
|
|
|
JSObject::ValidateElements(*array);
|
2014-04-07 10:00:14 +00:00
|
|
|
return array;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-17 15:01:45 +00:00
|
|
|
void Factory::NewJSArrayStorage(Handle<JSArray> array,
|
2014-04-14 16:05:19 +00:00
|
|
|
int length,
|
|
|
|
int capacity,
|
|
|
|
ArrayStorageAllocationMode mode) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(capacity >= length);
|
2014-04-14 16:05:19 +00:00
|
|
|
|
|
|
|
if (capacity == 0) {
|
2016-10-07 13:05:07 +00:00
|
|
|
array->set_length(Smi::kZero);
|
2014-04-14 16:05:19 +00:00
|
|
|
array->set_elements(*empty_fixed_array());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-12-18 12:50:02 +00:00
|
|
|
HandleScope inner_scope(isolate());
|
2014-04-14 16:05:19 +00:00
|
|
|
Handle<FixedArrayBase> elms;
|
|
|
|
ElementsKind elements_kind = array->GetElementsKind();
|
2017-06-30 18:00:44 +00:00
|
|
|
if (IsDoubleElementsKind(elements_kind)) {
|
2016-07-12 14:04:26 +00:00
|
|
|
if (mode == DONT_INITIALIZE_ARRAY_ELEMENTS) {
|
|
|
|
elms = NewFixedDoubleArray(capacity);
|
|
|
|
} else {
|
|
|
|
DCHECK(mode == INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
|
|
|
|
elms = NewFixedDoubleArrayWithHoles(capacity);
|
2014-04-14 16:05:19 +00:00
|
|
|
}
|
|
|
|
} else {
|
2017-06-30 18:00:44 +00:00
|
|
|
DCHECK(IsSmiOrObjectElementsKind(elements_kind));
|
2016-07-12 14:04:26 +00:00
|
|
|
if (mode == DONT_INITIALIZE_ARRAY_ELEMENTS) {
|
|
|
|
elms = NewUninitializedFixedArray(capacity);
|
|
|
|
} else {
|
|
|
|
DCHECK(mode == INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
|
|
|
|
elms = NewFixedArrayWithHoles(capacity);
|
2014-04-14 16:05:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
array->set_elements(*elms);
|
|
|
|
array->set_length(Smi::FromInt(length));
|
2014-03-17 15:01:45 +00:00
|
|
|
}
|
|
|
|
|
2016-10-07 19:37:04 +00:00
|
|
|
Handle<JSModuleNamespace> Factory::NewJSModuleNamespace() {
|
|
|
|
Handle<Map> map = isolate()->js_module_namespace_map();
|
2017-01-12 21:40:04 +00:00
|
|
|
Handle<JSModuleNamespace> module_namespace(
|
|
|
|
Handle<JSModuleNamespace>::cast(NewJSObjectFromMap(map)));
|
|
|
|
FieldIndex index = FieldIndex::ForDescriptor(
|
|
|
|
*map, JSModuleNamespace::kToStringTagFieldIndex);
|
2017-01-17 10:14:02 +00:00
|
|
|
module_namespace->FastPropertyAtPut(index,
|
|
|
|
isolate()->heap()->Module_string());
|
2017-01-12 21:40:04 +00:00
|
|
|
return module_namespace;
|
2016-10-07 19:37:04 +00:00
|
|
|
}
|
2014-03-17 15:01:45 +00:00
|
|
|
|
2013-11-05 12:11:27 +00:00
|
|
|
Handle<JSGeneratorObject> Factory::NewJSGeneratorObject(
|
|
|
|
Handle<JSFunction> function) {
|
2016-09-28 21:23:53 +00:00
|
|
|
DCHECK(IsResumableFunction(function->shared()->kind()));
|
2013-11-05 12:11:27 +00:00
|
|
|
JSFunction::EnsureHasInitialMap(function);
|
|
|
|
Handle<Map> map(function->initial_map());
|
[async-iteration] implement AsyncGenerator
- Introduce new struct AsyncGeneratorRequest, which holds
information pertinent to resuming execution of an
AsyncGenerator, such as the Promise associated with the async
generator request. It is intended to be used as a singly
linked list, and holds a pointer to the next item in te queue.
- Introduce JSAsyncGeneratorObject (subclass of
JSGeneratorObject), which includes several new internal fields
(`queue` which contains a singly linked list of
AsyncGeneratorRequest objects, and `await_input` which
contains the sent value from an Await expression (This is
necessary to prevent function.sent (used by yield*) from
having the sent value observably overwritten during
execution).
- Modify SuspendGenerator to accept a set of Flags, which
indicate whether the suspend is for a Yield or Await, and
whether it takes place on an async generator or ES6
generator.
- Introduce interpreter intrinsics and TF intrinsic lowering for
accessing the await input of an async generator
- Modify the JSGeneratorStore operator to understand whether or
not it's suspending for a normal yield, or an AsyncGenerator
Await. This ensures appropriate registers are stored.
- Add versions of ResumeGeneratorTrampoline which store the
input value in a different field depending on wether it's an
AsyncGenerator Await resume, or an ordinary resume. Also modifies
whether debug code will assert that the generator object is a
JSGeneratorObject or a JSAsyncGeneratorObject depending on the
resume type.
BUG=v8:5855
R=bmeurer@chromium.org, rmcilroy@chromium.org, jgruber@chromium.org,
littledan@chromium.org, neis@chromium.org
TBR=marja@chromium.org
Change-Id: I9d58df1d344465fc937fe7eed322424204497187
Reviewed-on: https://chromium-review.googlesource.com/446961
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44240}
2017-03-29 13:41:45 +00:00
|
|
|
|
|
|
|
DCHECK(map->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
|
|
|
|
map->instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE);
|
|
|
|
|
2014-04-08 06:15:20 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateJSObjectFromMap(*map),
|
|
|
|
JSGeneratorObject);
|
2013-11-05 12:11:27 +00:00
|
|
|
}
|
|
|
|
|
2016-09-20 18:49:58 +00:00
|
|
|
Handle<Module> Factory::NewModule(Handle<SharedFunctionInfo> code) {
|
|
|
|
Handle<ModuleInfo> module_info(code->scope_info()->ModuleDescriptorInfo(),
|
|
|
|
isolate());
|
|
|
|
Handle<ObjectHashTable> exports =
|
2016-11-07 09:55:25 +00:00
|
|
|
ObjectHashTable::New(isolate(), module_info->RegularExportCount());
|
2016-11-07 16:23:20 +00:00
|
|
|
Handle<FixedArray> regular_exports =
|
|
|
|
NewFixedArray(module_info->RegularExportCount());
|
|
|
|
Handle<FixedArray> regular_imports =
|
|
|
|
NewFixedArray(module_info->regular_imports()->length());
|
2016-09-20 18:49:58 +00:00
|
|
|
int requested_modules_length = module_info->module_requests()->length();
|
|
|
|
Handle<FixedArray> requested_modules =
|
|
|
|
requested_modules_length > 0 ? NewFixedArray(requested_modules_length)
|
|
|
|
: empty_fixed_array();
|
2016-09-26 22:42:09 +00:00
|
|
|
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<Module> module = Handle<Module>::cast(NewStruct(MODULE_TYPE, TENURED));
|
2016-09-16 21:47:14 +00:00
|
|
|
module->set_code(*code);
|
2016-09-16 16:47:07 +00:00
|
|
|
module->set_exports(*exports);
|
2016-11-07 16:23:20 +00:00
|
|
|
module->set_regular_exports(*regular_exports);
|
|
|
|
module->set_regular_imports(*regular_imports);
|
2016-10-10 16:56:15 +00:00
|
|
|
module->set_hash(isolate()->GenerateIdentityHash(Smi::kMaxValue));
|
2016-10-07 19:37:04 +00:00
|
|
|
module->set_module_namespace(isolate()->heap()->undefined_value());
|
|
|
|
module->set_requested_modules(*requested_modules);
|
2017-06-21 12:30:56 +00:00
|
|
|
module->set_script(Script::cast(code->script()));
|
2017-06-28 12:56:11 +00:00
|
|
|
module->set_status(Module::kUninstantiated);
|
|
|
|
module->set_exception(isolate()->heap()->the_hole_value());
|
2017-10-10 19:57:40 +00:00
|
|
|
module->set_import_meta(isolate()->heap()->the_hole_value());
|
2017-06-28 12:56:11 +00:00
|
|
|
module->set_dfs_index(-1);
|
|
|
|
module->set_dfs_ancestor_index(-1);
|
2016-09-12 12:54:47 +00:00
|
|
|
return module;
|
|
|
|
}
|
2013-11-05 12:11:27 +00:00
|
|
|
|
2015-09-17 14:47:37 +00:00
|
|
|
Handle<JSArrayBuffer> Factory::NewJSArrayBuffer(SharedFlag shared,
|
|
|
|
PretenureFlag pretenure) {
|
2013-08-06 19:14:51 +00:00
|
|
|
Handle<JSFunction> array_buffer_fun(
|
2015-05-22 13:43:38 +00:00
|
|
|
shared == SharedFlag::kShared
|
|
|
|
? isolate()->native_context()->shared_array_buffer_fun()
|
|
|
|
: isolate()->native_context()->array_buffer_fun());
|
2015-09-17 14:47:37 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->AllocateJSObject(
|
|
|
|
*array_buffer_fun, pretenure),
|
|
|
|
JSArrayBuffer);
|
2013-04-25 12:02:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-21 13:02:38 +00:00
|
|
|
Handle<JSDataView> Factory::NewJSDataView() {
|
2013-08-06 19:14:51 +00:00
|
|
|
Handle<JSFunction> data_view_fun(
|
2014-07-01 12:12:34 +00:00
|
|
|
isolate()->native_context()->data_view_fun());
|
2014-04-08 06:15:20 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(),
|
|
|
|
isolate()->heap()->AllocateJSObject(*data_view_fun),
|
|
|
|
JSDataView);
|
2013-06-21 13:02:38 +00:00
|
|
|
}
|
|
|
|
|
2016-09-21 14:17:42 +00:00
|
|
|
Handle<JSIteratorResult> Factory::NewJSIteratorResult(Handle<Object> value,
|
|
|
|
bool done) {
|
|
|
|
Handle<Map> map(isolate()->native_context()->iterator_result_map());
|
|
|
|
Handle<JSIteratorResult> js_iter_result =
|
|
|
|
Handle<JSIteratorResult>::cast(NewJSObjectFromMap(map));
|
|
|
|
js_iter_result->set_value(*value);
|
|
|
|
js_iter_result->set_done(*ToBoolean(done));
|
|
|
|
return js_iter_result;
|
|
|
|
}
|
2013-06-21 13:02:38 +00:00
|
|
|
|
2017-02-24 17:48:49 +00:00
|
|
|
Handle<JSAsyncFromSyncIterator> Factory::NewJSAsyncFromSyncIterator(
|
|
|
|
Handle<JSReceiver> sync_iterator) {
|
|
|
|
Handle<Map> map(isolate()->native_context()->async_from_sync_iterator_map());
|
|
|
|
Handle<JSAsyncFromSyncIterator> iterator =
|
|
|
|
Handle<JSAsyncFromSyncIterator>::cast(NewJSObjectFromMap(map));
|
|
|
|
|
|
|
|
iterator->set_sync_iterator(*sync_iterator);
|
|
|
|
return iterator;
|
|
|
|
}
|
|
|
|
|
2015-05-26 17:36:48 +00:00
|
|
|
Handle<JSMap> Factory::NewJSMap() {
|
|
|
|
Handle<Map> map(isolate()->native_context()->js_map_map());
|
|
|
|
Handle<JSMap> js_map = Handle<JSMap>::cast(NewJSObjectFromMap(map));
|
2015-08-26 12:46:10 +00:00
|
|
|
JSMap::Initialize(js_map, isolate());
|
2015-05-26 17:36:48 +00:00
|
|
|
return js_map;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<JSSet> Factory::NewJSSet() {
|
|
|
|
Handle<Map> map(isolate()->native_context()->js_set_map());
|
|
|
|
Handle<JSSet> js_set = Handle<JSSet>::cast(NewJSObjectFromMap(map));
|
2015-08-26 12:46:10 +00:00
|
|
|
JSSet::Initialize(js_set, isolate());
|
2015-05-26 17:36:48 +00:00
|
|
|
return js_set;
|
|
|
|
}
|
|
|
|
|
2017-07-10 06:46:56 +00:00
|
|
|
Handle<JSMapIterator> Factory::NewJSMapIterator(Handle<Map> map,
|
|
|
|
Handle<OrderedHashMap> table,
|
|
|
|
int index) {
|
2017-07-06 10:39:28 +00:00
|
|
|
Handle<JSMapIterator> result =
|
|
|
|
Handle<JSMapIterator>::cast(NewJSObjectFromMap(map));
|
|
|
|
result->set_table(*table);
|
|
|
|
result->set_index(Smi::FromInt(index));
|
|
|
|
return result;
|
2014-11-04 10:02:25 +00:00
|
|
|
}
|
|
|
|
|
2017-07-10 06:46:56 +00:00
|
|
|
Handle<JSSetIterator> Factory::NewJSSetIterator(Handle<Map> map,
|
|
|
|
Handle<OrderedHashSet> table,
|
|
|
|
int index) {
|
2017-07-06 10:39:28 +00:00
|
|
|
Handle<JSSetIterator> result =
|
|
|
|
Handle<JSSetIterator>::cast(NewJSObjectFromMap(map));
|
|
|
|
result->set_table(*table);
|
|
|
|
result->set_index(Smi::FromInt(index));
|
|
|
|
return result;
|
2014-11-04 10:02:25 +00:00
|
|
|
}
|
|
|
|
|
2017-03-02 13:35:39 +00:00
|
|
|
ExternalArrayType Factory::GetArrayTypeFromElementsKind(ElementsKind kind) {
|
|
|
|
switch (kind) {
|
2014-10-07 07:36:21 +00:00
|
|
|
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
2017-03-02 13:35:39 +00:00
|
|
|
case TYPE##_ELEMENTS: \
|
|
|
|
return kExternal##Type##Array;
|
2014-10-07 07:36:21 +00:00
|
|
|
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
2017-03-02 13:35:39 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
2014-10-07 07:36:21 +00:00
|
|
|
}
|
|
|
|
#undef TYPED_ARRAY_CASE
|
|
|
|
}
|
|
|
|
|
2017-03-02 13:35:39 +00:00
|
|
|
size_t Factory::GetExternalArrayElementSize(ExternalArrayType type) {
|
2014-10-10 08:10:29 +00:00
|
|
|
switch (type) {
|
|
|
|
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
|
|
|
case kExternal##Type##Array: \
|
|
|
|
return size;
|
|
|
|
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
2015-04-27 09:28:16 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
#undef TYPED_ARRAY_CASE
|
|
|
|
}
|
|
|
|
|
2017-03-02 13:35:39 +00:00
|
|
|
namespace {
|
2015-04-27 09:28:16 +00:00
|
|
|
|
2017-03-02 13:35:39 +00:00
|
|
|
ElementsKind GetExternalArrayElementsKind(ExternalArrayType type) {
|
|
|
|
switch (type) {
|
2015-04-27 09:28:16 +00:00
|
|
|
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
2017-03-02 13:35:39 +00:00
|
|
|
case kExternal##Type##Array: \
|
|
|
|
return TYPE##_ELEMENTS;
|
2015-04-27 09:28:16 +00:00
|
|
|
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
|
|
|
}
|
2017-03-02 13:35:39 +00:00
|
|
|
UNREACHABLE();
|
2015-04-27 09:28:16 +00:00
|
|
|
#undef TYPED_ARRAY_CASE
|
|
|
|
}
|
|
|
|
|
2017-03-02 13:35:39 +00:00
|
|
|
size_t GetFixedTypedArraysElementSize(ElementsKind kind) {
|
2015-04-27 09:28:16 +00:00
|
|
|
switch (kind) {
|
|
|
|
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
|
|
|
case TYPE##_ELEMENTS: \
|
2017-03-02 13:35:39 +00:00
|
|
|
return size;
|
2015-04-27 09:28:16 +00:00
|
|
|
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
2014-10-10 08:10:29 +00:00
|
|
|
}
|
|
|
|
#undef TYPED_ARRAY_CASE
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-07 07:36:21 +00:00
|
|
|
JSFunction* GetTypedArrayFun(ExternalArrayType type, Isolate* isolate) {
|
2013-08-06 19:14:51 +00:00
|
|
|
Context* native_context = isolate->context()->native_context();
|
2013-04-29 11:09:03 +00:00
|
|
|
switch (type) {
|
2014-01-24 16:01:15 +00:00
|
|
|
#define TYPED_ARRAY_FUN(Type, type, TYPE, ctype, size) \
|
|
|
|
case kExternal##Type##Array: \
|
|
|
|
return native_context->type##_array_fun();
|
2013-04-29 11:09:03 +00:00
|
|
|
|
2014-01-24 16:01:15 +00:00
|
|
|
TYPED_ARRAYS(TYPED_ARRAY_FUN)
|
|
|
|
#undef TYPED_ARRAY_FUN
|
2013-05-02 11:36:48 +00:00
|
|
|
|
2013-04-29 11:09:03 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2013-08-06 19:14:51 +00:00
|
|
|
}
|
|
|
|
|
2014-10-17 09:04:58 +00:00
|
|
|
|
2015-04-27 09:28:16 +00:00
|
|
|
JSFunction* GetTypedArrayFun(ElementsKind elements_kind, Isolate* isolate) {
|
|
|
|
Context* native_context = isolate->context()->native_context();
|
|
|
|
switch (elements_kind) {
|
|
|
|
#define TYPED_ARRAY_FUN(Type, type, TYPE, ctype, size) \
|
|
|
|
case TYPE##_ELEMENTS: \
|
|
|
|
return native_context->type##_array_fun();
|
|
|
|
|
|
|
|
TYPED_ARRAYS(TYPED_ARRAY_FUN)
|
|
|
|
#undef TYPED_ARRAY_FUN
|
|
|
|
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-17 09:04:58 +00:00
|
|
|
void SetupArrayBufferView(i::Isolate* isolate,
|
|
|
|
i::Handle<i::JSArrayBufferView> obj,
|
|
|
|
i::Handle<i::JSArrayBuffer> buffer,
|
2015-09-17 14:47:37 +00:00
|
|
|
size_t byte_offset, size_t byte_length,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED) {
|
2014-10-17 09:04:58 +00:00
|
|
|
DCHECK(byte_offset + byte_length <=
|
|
|
|
static_cast<size_t>(buffer->byte_length()->Number()));
|
|
|
|
|
2017-03-17 13:26:05 +00:00
|
|
|
DCHECK_EQ(obj->GetEmbedderFieldCount(),
|
|
|
|
v8::ArrayBufferView::kEmbedderFieldCount);
|
|
|
|
for (int i = 0; i < v8::ArrayBufferView::kEmbedderFieldCount; i++) {
|
|
|
|
obj->SetEmbedderField(i, Smi::kZero);
|
2016-11-15 22:42:40 +00:00
|
|
|
}
|
|
|
|
|
2014-10-17 09:04:58 +00:00
|
|
|
obj->set_buffer(*buffer);
|
|
|
|
|
|
|
|
i::Handle<i::Object> byte_offset_object =
|
2015-09-17 14:47:37 +00:00
|
|
|
isolate->factory()->NewNumberFromSize(byte_offset, pretenure);
|
2014-10-17 09:04:58 +00:00
|
|
|
obj->set_byte_offset(*byte_offset_object);
|
|
|
|
|
|
|
|
i::Handle<i::Object> byte_length_object =
|
2015-09-17 14:47:37 +00:00
|
|
|
isolate->factory()->NewNumberFromSize(byte_length, pretenure);
|
2014-10-17 09:04:58 +00:00
|
|
|
obj->set_byte_length(*byte_length_object);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-07 07:36:21 +00:00
|
|
|
} // namespace
|
|
|
|
|
2013-08-06 19:14:51 +00:00
|
|
|
|
2015-09-17 14:47:37 +00:00
|
|
|
Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
|
|
|
|
PretenureFlag pretenure) {
|
2013-08-06 19:14:51 +00:00
|
|
|
Handle<JSFunction> typed_array_fun_handle(GetTypedArrayFun(type, isolate()));
|
2014-04-08 06:15:20 +00:00
|
|
|
|
2015-09-17 14:47:37 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->AllocateJSObject(
|
|
|
|
*typed_array_fun_handle, pretenure),
|
|
|
|
JSTypedArray);
|
2013-04-29 11:09:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-17 14:47:37 +00:00
|
|
|
Handle<JSTypedArray> Factory::NewJSTypedArray(ElementsKind elements_kind,
|
|
|
|
PretenureFlag pretenure) {
|
2015-04-27 09:28:16 +00:00
|
|
|
Handle<JSFunction> typed_array_fun_handle(
|
|
|
|
GetTypedArrayFun(elements_kind, isolate()));
|
|
|
|
|
2015-09-17 14:47:37 +00:00
|
|
|
CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->AllocateJSObject(
|
|
|
|
*typed_array_fun_handle, pretenure),
|
|
|
|
JSTypedArray);
|
2015-04-27 09:28:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-07 07:36:21 +00:00
|
|
|
Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
|
|
|
|
Handle<JSArrayBuffer> buffer,
|
2015-09-17 14:47:37 +00:00
|
|
|
size_t byte_offset, size_t length,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
Handle<JSTypedArray> obj = NewJSTypedArray(type, pretenure);
|
2014-10-17 09:04:58 +00:00
|
|
|
|
|
|
|
size_t element_size = GetExternalArrayElementSize(type);
|
|
|
|
ElementsKind elements_kind = GetExternalArrayElementsKind(type);
|
|
|
|
|
2017-10-18 09:06:55 +00:00
|
|
|
CHECK_EQ(byte_offset % element_size, 0);
|
2014-10-17 09:04:58 +00:00
|
|
|
|
|
|
|
CHECK(length <= (std::numeric_limits<size_t>::max() / element_size));
|
|
|
|
CHECK(length <= static_cast<size_t>(Smi::kMaxValue));
|
|
|
|
size_t byte_length = length * element_size;
|
2015-09-17 14:47:37 +00:00
|
|
|
SetupArrayBufferView(isolate(), obj, buffer, byte_offset, byte_length,
|
|
|
|
pretenure);
|
2014-10-17 09:04:58 +00:00
|
|
|
|
2015-09-17 14:47:37 +00:00
|
|
|
Handle<Object> length_object = NewNumberFromSize(length, pretenure);
|
2014-10-17 09:04:58 +00:00
|
|
|
obj->set_length(*length_object);
|
|
|
|
|
2015-07-28 09:29:34 +00:00
|
|
|
Handle<FixedTypedArrayBase> elements = NewFixedTypedArrayWithExternalPointer(
|
2014-10-17 09:04:58 +00:00
|
|
|
static_cast<int>(length), type,
|
2015-09-17 14:47:37 +00:00
|
|
|
static_cast<uint8_t*>(buffer->backing_store()) + byte_offset, pretenure);
|
2014-10-17 09:04:58 +00:00
|
|
|
Handle<Map> map = JSObject::GetElementsTransitionMap(obj, elements_kind);
|
|
|
|
JSObject::SetMapAndElements(obj, map, elements);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-27 09:28:16 +00:00
|
|
|
Handle<JSTypedArray> Factory::NewJSTypedArray(ElementsKind elements_kind,
|
2015-09-17 14:47:37 +00:00
|
|
|
size_t number_of_elements,
|
|
|
|
PretenureFlag pretenure) {
|
|
|
|
Handle<JSTypedArray> obj = NewJSTypedArray(elements_kind, pretenure);
|
2017-03-17 13:26:05 +00:00
|
|
|
DCHECK_EQ(obj->GetEmbedderFieldCount(),
|
|
|
|
v8::ArrayBufferView::kEmbedderFieldCount);
|
|
|
|
for (int i = 0; i < v8::ArrayBufferView::kEmbedderFieldCount; i++) {
|
|
|
|
obj->SetEmbedderField(i, Smi::kZero);
|
2016-11-15 22:42:40 +00:00
|
|
|
}
|
2015-04-27 09:28:16 +00:00
|
|
|
|
|
|
|
size_t element_size = GetFixedTypedArraysElementSize(elements_kind);
|
|
|
|
ExternalArrayType array_type = GetArrayTypeFromElementsKind(elements_kind);
|
|
|
|
|
|
|
|
CHECK(number_of_elements <=
|
|
|
|
(std::numeric_limits<size_t>::max() / element_size));
|
|
|
|
CHECK(number_of_elements <= static_cast<size_t>(Smi::kMaxValue));
|
|
|
|
size_t byte_length = number_of_elements * element_size;
|
|
|
|
|
2016-10-07 13:05:07 +00:00
|
|
|
obj->set_byte_offset(Smi::kZero);
|
2015-04-27 09:28:16 +00:00
|
|
|
i::Handle<i::Object> byte_length_object =
|
2015-09-17 14:47:37 +00:00
|
|
|
NewNumberFromSize(byte_length, pretenure);
|
2015-04-27 09:28:16 +00:00
|
|
|
obj->set_byte_length(*byte_length_object);
|
2015-09-17 14:47:37 +00:00
|
|
|
Handle<Object> length_object =
|
|
|
|
NewNumberFromSize(number_of_elements, pretenure);
|
2015-04-27 09:28:16 +00:00
|
|
|
obj->set_length(*length_object);
|
|
|
|
|
2015-09-17 14:47:37 +00:00
|
|
|
Handle<JSArrayBuffer> buffer =
|
|
|
|
NewJSArrayBuffer(SharedFlag::kNotShared, pretenure);
|
2017-10-13 16:33:03 +00:00
|
|
|
JSArrayBuffer::Setup(buffer, isolate(), true, nullptr, byte_length,
|
2015-08-26 13:59:35 +00:00
|
|
|
SharedFlag::kNotShared);
|
2015-04-30 13:46:27 +00:00
|
|
|
obj->set_buffer(*buffer);
|
2015-09-17 14:47:37 +00:00
|
|
|
Handle<FixedTypedArrayBase> elements = NewFixedTypedArray(
|
|
|
|
static_cast<int>(number_of_elements), array_type, true, pretenure);
|
2015-04-27 09:28:16 +00:00
|
|
|
obj->set_elements(*elements);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-17 09:04:58 +00:00
|
|
|
Handle<JSDataView> Factory::NewJSDataView(Handle<JSArrayBuffer> buffer,
|
|
|
|
size_t byte_offset,
|
|
|
|
size_t byte_length) {
|
|
|
|
Handle<JSDataView> obj = NewJSDataView();
|
|
|
|
SetupArrayBufferView(isolate(), obj, buffer, byte_offset, byte_length);
|
|
|
|
return obj;
|
2014-10-07 07:36:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-27 06:30:53 +00:00
|
|
|
MaybeHandle<JSBoundFunction> Factory::NewJSBoundFunction(
|
|
|
|
Handle<JSReceiver> target_function, Handle<Object> bound_this,
|
|
|
|
Vector<Handle<Object>> bound_args) {
|
|
|
|
DCHECK(target_function->IsCallable());
|
|
|
|
STATIC_ASSERT(Code::kMaxArguments <= FixedArray::kMaxLength);
|
|
|
|
if (bound_args.length() >= Code::kMaxArguments) {
|
|
|
|
THROW_NEW_ERROR(isolate(),
|
|
|
|
NewRangeError(MessageTemplate::kTooManyArguments),
|
|
|
|
JSBoundFunction);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine the prototype of the {target_function}.
|
|
|
|
Handle<Object> prototype;
|
2016-02-08 13:49:47 +00:00
|
|
|
ASSIGN_RETURN_ON_EXCEPTION(
|
|
|
|
isolate(), prototype,
|
|
|
|
JSReceiver::GetPrototype(isolate(), target_function), JSBoundFunction);
|
2015-12-27 06:30:53 +00:00
|
|
|
|
2017-10-26 07:46:14 +00:00
|
|
|
SaveContext save(isolate());
|
|
|
|
isolate()->set_context(*target_function->GetCreationContext());
|
|
|
|
|
2015-12-27 06:30:53 +00:00
|
|
|
// Create the [[BoundArguments]] for the result.
|
|
|
|
Handle<FixedArray> bound_arguments;
|
|
|
|
if (bound_args.length() == 0) {
|
|
|
|
bound_arguments = empty_fixed_array();
|
|
|
|
} else {
|
|
|
|
bound_arguments = NewFixedArray(bound_args.length());
|
|
|
|
for (int i = 0; i < bound_args.length(); ++i) {
|
|
|
|
bound_arguments->set(i, *bound_args[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup the map for the JSBoundFunction instance.
|
2016-04-07 13:36:40 +00:00
|
|
|
Handle<Map> map = target_function->IsConstructor()
|
|
|
|
? isolate()->bound_function_with_constructor_map()
|
|
|
|
: isolate()->bound_function_without_constructor_map();
|
2015-12-27 06:30:53 +00:00
|
|
|
if (map->prototype() != *prototype) {
|
2017-06-07 14:33:27 +00:00
|
|
|
map = Map::TransitionToPrototype(map, prototype);
|
2015-12-27 06:30:53 +00:00
|
|
|
}
|
|
|
|
DCHECK_EQ(target_function->IsConstructor(), map->is_constructor());
|
|
|
|
|
|
|
|
// Setup the JSBoundFunction instance.
|
|
|
|
Handle<JSBoundFunction> result =
|
|
|
|
Handle<JSBoundFunction>::cast(NewJSObjectFromMap(map));
|
|
|
|
result->set_bound_target_function(*target_function);
|
|
|
|
result->set_bound_this(*bound_this);
|
|
|
|
result->set_bound_arguments(*bound_arguments);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-22 16:36:47 +00:00
|
|
|
// ES6 section 9.5.15 ProxyCreate (target, handler)
|
2015-11-12 22:11:53 +00:00
|
|
|
Handle<JSProxy> Factory::NewJSProxy(Handle<JSReceiver> target,
|
2015-11-13 14:13:50 +00:00
|
|
|
Handle<JSReceiver> handler) {
|
2014-04-16 13:35:36 +00:00
|
|
|
// Allocate the proxy object.
|
2015-12-08 16:04:08 +00:00
|
|
|
Handle<Map> map;
|
|
|
|
if (target->IsCallable()) {
|
|
|
|
if (target->IsConstructor()) {
|
|
|
|
map = Handle<Map>(isolate()->proxy_constructor_map());
|
|
|
|
} else {
|
|
|
|
map = Handle<Map>(isolate()->proxy_callable_map());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
map = Handle<Map>(isolate()->proxy_map());
|
|
|
|
}
|
2016-06-14 10:08:44 +00:00
|
|
|
DCHECK(map->prototype()->IsNull(isolate()));
|
2014-04-16 13:35:36 +00:00
|
|
|
Handle<JSProxy> result = New<JSProxy>(map, NEW_SPACE);
|
2016-01-12 15:43:41 +00:00
|
|
|
result->initialize_properties();
|
2015-11-12 22:11:53 +00:00
|
|
|
result->set_target(*target);
|
2014-04-16 13:35:36 +00:00
|
|
|
result->set_handler(*handler);
|
|
|
|
return result;
|
2011-05-13 10:58:25 +00:00
|
|
|
}
|
|
|
|
|
2016-11-04 10:02:02 +00:00
|
|
|
Handle<JSGlobalProxy> Factory::NewUninitializedJSGlobalProxy(int size) {
|
2015-01-14 16:42:15 +00:00
|
|
|
// Create an empty shell of a JSGlobalProxy that needs to be reinitialized
|
|
|
|
// via ReinitializeJSGlobalProxy later.
|
2016-11-04 10:02:02 +00:00
|
|
|
Handle<Map> map = NewMap(JS_GLOBAL_PROXY_TYPE, size);
|
2015-01-14 16:42:15 +00:00
|
|
|
// Maintain invariant expected from any JSGlobalProxy.
|
|
|
|
map->set_is_access_check_needed(true);
|
[builtins] Speed-up Object.prototype.toString.
The @@toStringTag lookup in Object.prototype.toString causes quite a
lot of overhead and oftentimes dominates the builtin performance. These
lookups are almost always negative, especially for primitive values,
and Object.prototype.toString is often used to implement predicates
(like in Node core or in AngularJS), so having a way to skip the
negative lookup yields big performance gains.
This CL introduces a "MayHaveInterestingSymbols" bit on every map,
which says whether instances with this map may have an interesting
symbol. Currently only @@toStringTag is considered an interesting
symbol, but we can extend that in the future.
In the Object.prototype.toString we can use the interesting symbols
bit to do a quick check on the prototype chain to see if there are
any maps that might have the @@toStringTag, and if not, we can just
immediately return the result, which is very fast because it's derived
from the instance type. This also avoids the ToObject conversions for
primitive values, which is important, since this causes unnecessary
GC traffic and in for example AngularJS, strings are also often probed
via the Object.prototype.toString based predicates.
This boosts Speedometer/AngularJS by over 3% and Speedometer overall
by up to 1%. On the microbenchmark from the similar SpiderMonkey bug
(https://bugzilla.mozilla.org/show_bug.cgi?id=1369042), we go from
roughly 450ms to 70ms, which corresponds to a 6.5x improvement.
```
function f() {
var res = "";
var a = [1, 2, 3];
var toString = Object.prototype.toString;
var t = new Date;
for (var i = 0; i < 5000000; i++)
res = toString.call(a);
print(new Date - t);
return res;
}
f();
```
The design document at https://goo.gl/e8CruQ has some additional
data points.
TBR=ulan@chromium.org
Bug: v8:6654
Change-Id: I31932cf41ecddad079d294e2c322a852af0ed244
Reviewed-on: https://chromium-review.googlesource.com/593620
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47034}
2017-08-01 08:11:14 +00:00
|
|
|
map->set_may_have_interesting_symbols(true);
|
2015-07-13 08:26:21 +00:00
|
|
|
CALL_HEAP_FUNCTION(
|
|
|
|
isolate(), isolate()->heap()->AllocateJSObjectFromMap(*map, NOT_TENURED),
|
|
|
|
JSGlobalProxy);
|
2015-01-14 16:42:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-15 11:51:34 +00:00
|
|
|
void Factory::ReinitializeJSGlobalProxy(Handle<JSGlobalProxy> object,
|
|
|
|
Handle<JSFunction> constructor) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(constructor->has_initial_map());
|
2014-04-15 11:51:34 +00:00
|
|
|
Handle<Map> map(constructor->initial_map(), isolate());
|
2016-01-05 16:15:00 +00:00
|
|
|
Handle<Map> old_map(object->map(), isolate());
|
2014-04-15 11:51:34 +00:00
|
|
|
|
2014-05-05 18:27:57 +00:00
|
|
|
// The proxy's hash should be retained across reinitialization.
|
2017-10-25 12:16:53 +00:00
|
|
|
Handle<Object> raw_properties_or_hash(object->raw_properties_or_hash(),
|
|
|
|
isolate());
|
2014-05-05 18:27:57 +00:00
|
|
|
|
2016-01-05 16:15:00 +00:00
|
|
|
if (old_map->is_prototype_map()) {
|
|
|
|
map = Map::Copy(map, "CopyAsPrototypeForJSGlobalProxy");
|
|
|
|
map->set_is_prototype_map(true);
|
|
|
|
}
|
2016-11-16 17:44:39 +00:00
|
|
|
JSObject::NotifyMapChange(old_map, map, isolate());
|
2017-02-28 16:38:04 +00:00
|
|
|
old_map->NotifyLeafMapLayoutChange();
|
2016-01-05 16:15:00 +00:00
|
|
|
|
2014-04-15 11:51:34 +00:00
|
|
|
// Check that the already allocated object has the same size and type as
|
|
|
|
// objects allocated using the constructor.
|
2016-01-05 16:15:00 +00:00
|
|
|
DCHECK(map->instance_size() == old_map->instance_size());
|
|
|
|
DCHECK(map->instance_type() == old_map->instance_type());
|
2014-04-15 11:51:34 +00:00
|
|
|
|
|
|
|
// In order to keep heap in consistent state there must be no allocations
|
|
|
|
// before object re-initialization is finished.
|
|
|
|
DisallowHeapAllocation no_allocation;
|
|
|
|
|
|
|
|
// Reset the map for the object.
|
2014-06-24 14:53:48 +00:00
|
|
|
object->synchronized_set_map(*map);
|
2014-04-15 11:51:34 +00:00
|
|
|
|
|
|
|
Heap* heap = isolate()->heap();
|
|
|
|
// Reinitialize the object from the constructor map.
|
2017-10-25 12:16:53 +00:00
|
|
|
heap->InitializeJSObjectFromMap(*object, *raw_properties_or_hash, *map);
|
2014-04-15 11:51:34 +00:00
|
|
|
}
|
|
|
|
|
2010-03-23 06:04:44 +00:00
|
|
|
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
|
2017-06-06 16:23:49 +00:00
|
|
|
MaybeHandle<String> name, FunctionKind kind, Handle<Code> code,
|
2017-02-15 15:12:13 +00:00
|
|
|
Handle<ScopeInfo> scope_info) {
|
2014-09-10 16:39:42 +00:00
|
|
|
DCHECK(IsValidFunctionKind(kind));
|
2017-03-27 19:20:24 +00:00
|
|
|
Handle<SharedFunctionInfo> shared =
|
2017-07-13 09:33:22 +00:00
|
|
|
NewSharedFunctionInfo(name, code, IsConstructable(kind), kind);
|
2010-07-13 13:06:33 +00:00
|
|
|
shared->set_scope_info(*scope_info);
|
2016-09-20 12:07:52 +00:00
|
|
|
shared->set_outer_scope_info(*the_hole_value());
|
2014-09-10 16:39:42 +00:00
|
|
|
if (IsGeneratorFunction(kind)) {
|
2013-04-17 15:01:25 +00:00
|
|
|
shared->set_instance_class_name(isolate()->heap()->Generator_string());
|
|
|
|
}
|
2010-03-23 06:04:44 +00:00
|
|
|
return shared;
|
|
|
|
}
|
|
|
|
|
2016-11-30 00:25:21 +00:00
|
|
|
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForLiteral(
|
|
|
|
FunctionLiteral* literal, Handle<Script> script) {
|
2017-08-01 08:15:46 +00:00
|
|
|
Handle<Code> code = BUILTIN_CODE(isolate(), CompileLazy);
|
2016-11-30 00:25:21 +00:00
|
|
|
Handle<ScopeInfo> scope_info(ScopeInfo::Empty(isolate()));
|
2017-02-15 15:12:13 +00:00
|
|
|
Handle<SharedFunctionInfo> result =
|
|
|
|
NewSharedFunctionInfo(literal->name(), literal->kind(), code, scope_info);
|
2016-11-30 00:25:21 +00:00
|
|
|
SharedFunctionInfo::InitFromFunctionLiteral(result, literal);
|
2017-06-30 10:38:38 +00:00
|
|
|
SharedFunctionInfo::SetScript(result, script, false);
|
2016-11-30 00:25:21 +00:00
|
|
|
return result;
|
|
|
|
}
|
2010-03-23 06:04:44 +00:00
|
|
|
|
2011-02-02 13:31:52 +00:00
|
|
|
Handle<JSMessageObject> Factory::NewJSMessageObject(
|
2015-05-18 08:34:05 +00:00
|
|
|
MessageTemplate::Template message, Handle<Object> argument,
|
|
|
|
int start_position, int end_position, Handle<Object> script,
|
2011-02-02 13:31:52 +00:00
|
|
|
Handle<Object> stack_frames) {
|
2014-04-16 13:35:36 +00:00
|
|
|
Handle<Map> map = message_object_map();
|
2015-05-18 08:34:05 +00:00
|
|
|
Handle<JSMessageObject> message_obj = New<JSMessageObject>(map, NEW_SPACE);
|
2017-07-17 23:30:32 +00:00
|
|
|
message_obj->set_raw_properties_or_hash(*empty_fixed_array(),
|
|
|
|
SKIP_WRITE_BARRIER);
|
2015-05-18 08:34:05 +00:00
|
|
|
message_obj->initialize_elements();
|
|
|
|
message_obj->set_elements(*empty_fixed_array(), SKIP_WRITE_BARRIER);
|
|
|
|
message_obj->set_type(message);
|
|
|
|
message_obj->set_argument(*argument);
|
|
|
|
message_obj->set_start_position(start_position);
|
|
|
|
message_obj->set_end_position(end_position);
|
|
|
|
message_obj->set_script(*script);
|
|
|
|
message_obj->set_stack_frames(*stack_frames);
|
2016-12-12 14:47:56 +00:00
|
|
|
message_obj->set_error_level(v8::Isolate::kMessageError);
|
2015-05-18 08:34:05 +00:00
|
|
|
return message_obj;
|
2011-02-02 13:31:52 +00:00
|
|
|
}
|
|
|
|
|
2014-05-09 17:39:54 +00:00
|
|
|
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
|
2017-06-06 16:23:49 +00:00
|
|
|
MaybeHandle<String> maybe_name, MaybeHandle<Code> maybe_code,
|
2017-11-08 12:56:08 +00:00
|
|
|
bool is_constructor, FunctionKind kind, int maybe_builtin_index) {
|
2016-02-11 19:54:26 +00:00
|
|
|
// Function names are assumed to be flat elsewhere. Must flatten before
|
|
|
|
// allocating SharedFunctionInfo to avoid GC seeing the uninitialized SFI.
|
2017-06-06 16:23:49 +00:00
|
|
|
Handle<String> shared_name;
|
|
|
|
bool has_shared_name = maybe_name.ToHandle(&shared_name);
|
|
|
|
if (has_shared_name) {
|
|
|
|
shared_name = String::Flatten(shared_name, TENURED);
|
|
|
|
}
|
2016-02-11 19:54:26 +00:00
|
|
|
|
2014-04-16 13:35:36 +00:00
|
|
|
Handle<Map> map = shared_function_info_map();
|
2015-04-07 11:31:57 +00:00
|
|
|
Handle<SharedFunctionInfo> share = New<SharedFunctionInfo>(map, OLD_SPACE);
|
2014-04-16 13:35:36 +00:00
|
|
|
|
|
|
|
// Set pointer fields.
|
2017-06-06 16:23:49 +00:00
|
|
|
share->set_raw_name(has_shared_name
|
|
|
|
? *shared_name
|
|
|
|
: SharedFunctionInfo::kNoSharedNameSentinel);
|
2014-05-09 17:39:54 +00:00
|
|
|
Handle<Code> code;
|
|
|
|
if (!maybe_code.ToHandle(&code)) {
|
2017-08-01 08:15:46 +00:00
|
|
|
code = BUILTIN_CODE(isolate(), Illegal);
|
2014-05-09 17:39:54 +00:00
|
|
|
}
|
2017-11-08 12:56:08 +00:00
|
|
|
Object* function_data = (Builtins::IsBuiltinId(maybe_builtin_index) &&
|
|
|
|
Builtins::IsLazy(maybe_builtin_index))
|
|
|
|
? Smi::FromInt(maybe_builtin_index)
|
|
|
|
: Object::cast(*undefined_value());
|
2017-08-30 12:03:43 +00:00
|
|
|
share->set_function_data(function_data, SKIP_WRITE_BARRIER);
|
2014-05-09 17:39:54 +00:00
|
|
|
share->set_code(*code);
|
2014-04-16 13:35:36 +00:00
|
|
|
share->set_scope_info(ScopeInfo::Empty(isolate()));
|
2016-09-20 12:07:52 +00:00
|
|
|
share->set_outer_scope_info(*the_hole_value());
|
2017-11-08 12:56:08 +00:00
|
|
|
DCHECK(!Builtins::IsLazy(Builtins::kConstructedNonConstructable));
|
2015-11-24 17:16:40 +00:00
|
|
|
Handle<Code> construct_stub =
|
|
|
|
is_constructor ? isolate()->builtins()->JSConstructStubGeneric()
|
2017-08-01 08:15:46 +00:00
|
|
|
: BUILTIN_CODE(isolate(), ConstructedNonConstructable);
|
2016-07-11 10:03:02 +00:00
|
|
|
share->SetConstructStub(*construct_stub);
|
2014-04-16 13:35:36 +00:00
|
|
|
share->set_instance_class_name(*Object_string());
|
|
|
|
share->set_script(*undefined_value(), SKIP_WRITE_BARRIER);
|
2017-01-23 10:25:02 +00:00
|
|
|
share->set_debug_info(Smi::kZero, SKIP_WRITE_BARRIER);
|
2016-03-17 16:37:36 +00:00
|
|
|
share->set_function_identifier(*undefined_value(), SKIP_WRITE_BARRIER);
|
2015-09-28 11:41:40 +00:00
|
|
|
StaticFeedbackVectorSpec empty_spec;
|
2017-02-07 14:05:02 +00:00
|
|
|
Handle<FeedbackMetadata> feedback_metadata =
|
|
|
|
FeedbackMetadata::New(isolate(), &empty_spec);
|
2016-05-27 08:09:12 +00:00
|
|
|
share->set_feedback_metadata(*feedback_metadata, SKIP_WRITE_BARRIER);
|
2016-11-28 11:40:22 +00:00
|
|
|
share->set_function_literal_id(FunctionLiteral::kIdTypeInvalid);
|
2017-05-16 15:52:10 +00:00
|
|
|
#if V8_SFI_HAS_UNIQUE_ID
|
2014-11-07 16:03:11 +00:00
|
|
|
share->set_unique_id(isolate()->GetNextUniqueSharedFunctionInfoId());
|
|
|
|
#endif
|
2014-04-16 13:35:36 +00:00
|
|
|
|
|
|
|
// Set integer fields (smi or int, depending on the architecture).
|
|
|
|
share->set_length(0);
|
2015-02-11 09:47:32 +00:00
|
|
|
share->set_internal_formal_parameter_count(0);
|
2014-04-16 13:35:36 +00:00
|
|
|
share->set_expected_nof_properties(0);
|
|
|
|
share->set_start_position_and_type(0);
|
|
|
|
share->set_end_position(0);
|
|
|
|
share->set_function_token_position(0);
|
|
|
|
// All compiler hints default to false or 0.
|
|
|
|
share->set_compiler_hints(0);
|
2017-07-13 09:33:22 +00:00
|
|
|
share->set_kind(kind);
|
2014-04-16 13:35:36 +00:00
|
|
|
|
2017-06-30 10:38:38 +00:00
|
|
|
share->set_preparsed_scope_data(*null_value());
|
|
|
|
|
2017-08-02 13:05:45 +00:00
|
|
|
share->clear_padding();
|
|
|
|
|
2015-10-27 11:40:31 +00:00
|
|
|
// Link into the list.
|
|
|
|
Handle<Object> new_noscript_list =
|
|
|
|
WeakFixedArray::Add(noscript_shared_function_infos(), share);
|
|
|
|
isolate()->heap()->set_noscript_shared_function_infos(*new_noscript_list);
|
|
|
|
|
2017-07-13 09:33:22 +00:00
|
|
|
#ifdef VERIFY_HEAP
|
|
|
|
share->SharedFunctionInfoVerify();
|
|
|
|
#endif
|
2014-04-16 13:35:36 +00:00
|
|
|
return share;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 14:04:54 +00:00
|
|
|
static inline int NumberCacheHash(Handle<FixedArray> cache,
|
|
|
|
Handle<Object> number) {
|
|
|
|
int mask = (cache->length() >> 1) - 1;
|
|
|
|
if (number->IsSmi()) {
|
|
|
|
return Handle<Smi>::cast(number)->value() & mask;
|
|
|
|
} else {
|
2016-06-29 11:58:13 +00:00
|
|
|
int64_t bits = bit_cast<int64_t>(number->Number());
|
|
|
|
return (static_cast<int>(bits) ^ static_cast<int>(bits >> 32)) & mask;
|
2014-04-16 14:04:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handle<Object> Factory::GetNumberStringCache(Handle<Object> number) {
|
|
|
|
DisallowHeapAllocation no_gc;
|
|
|
|
int hash = NumberCacheHash(number_string_cache(), number);
|
|
|
|
Object* key = number_string_cache()->get(hash * 2);
|
|
|
|
if (key == *number || (key->IsHeapNumber() && number->IsHeapNumber() &&
|
|
|
|
key->Number() == number->Number())) {
|
|
|
|
return Handle<String>(
|
|
|
|
String::cast(number_string_cache()->get(hash * 2 + 1)), isolate());
|
|
|
|
}
|
|
|
|
return undefined_value();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Factory::SetNumberStringCache(Handle<Object> number,
|
|
|
|
Handle<String> string) {
|
|
|
|
int hash = NumberCacheHash(number_string_cache(), number);
|
|
|
|
if (number_string_cache()->get(hash * 2) != *undefined_value()) {
|
|
|
|
int full_size = isolate()->heap()->FullSizeNumberStringCacheLength();
|
|
|
|
if (number_string_cache()->length() != full_size) {
|
|
|
|
Handle<FixedArray> new_cache = NewFixedArray(full_size, TENURED);
|
|
|
|
isolate()->heap()->set_number_string_cache(*new_cache);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
number_string_cache()->set(hash * 2, *number);
|
|
|
|
number_string_cache()->set(hash * 2 + 1, *string);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-15 11:16:02 +00:00
|
|
|
Handle<String> Factory::NumberToString(Handle<Object> number,
|
|
|
|
bool check_number_string_cache) {
|
2014-04-16 14:04:54 +00:00
|
|
|
isolate()->counters()->number_to_string_runtime()->Increment();
|
|
|
|
if (check_number_string_cache) {
|
|
|
|
Handle<Object> cached = GetNumberStringCache(number);
|
2016-06-06 12:58:10 +00:00
|
|
|
if (!cached->IsUndefined(isolate())) return Handle<String>::cast(cached);
|
2014-04-16 14:04:54 +00:00
|
|
|
}
|
2009-10-02 13:43:16 +00:00
|
|
|
|
2014-04-16 14:04:54 +00:00
|
|
|
char arr[100];
|
2014-08-26 09:19:24 +00:00
|
|
|
Vector<char> buffer(arr, arraysize(arr));
|
2014-04-16 14:04:54 +00:00
|
|
|
const char* str;
|
|
|
|
if (number->IsSmi()) {
|
|
|
|
int num = Handle<Smi>::cast(number)->value();
|
|
|
|
str = IntToCString(num, buffer);
|
|
|
|
} else {
|
|
|
|
double num = Handle<HeapNumber>::cast(number)->value();
|
|
|
|
str = DoubleToCString(num, buffer);
|
|
|
|
}
|
2009-10-02 13:43:16 +00:00
|
|
|
|
2014-04-16 14:04:54 +00:00
|
|
|
// We tenure the allocated string since it is referenced from the
|
|
|
|
// number-string cache which lives in the old space.
|
2014-04-17 13:27:02 +00:00
|
|
|
Handle<String> js_string = NewStringFromAsciiChecked(str, TENURED);
|
2014-04-16 14:04:54 +00:00
|
|
|
SetNumberStringCache(number, js_string);
|
|
|
|
return js_string;
|
2011-09-22 10:45:37 +00:00
|
|
|
}
|
|
|
|
|
2008-09-01 10:15:45 +00:00
|
|
|
Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
|
2017-01-23 10:25:02 +00:00
|
|
|
DCHECK(!shared->HasDebugInfo());
|
2017-05-31 14:26:58 +00:00
|
|
|
Heap* heap = isolate()->heap();
|
|
|
|
|
2008-09-01 10:15:45 +00:00
|
|
|
Handle<DebugInfo> debug_info =
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<DebugInfo>::cast(NewStruct(DEBUG_INFO_TYPE, TENURED));
|
2017-05-31 14:26:58 +00:00
|
|
|
debug_info->set_flags(DebugInfo::kNone);
|
2008-09-01 10:15:45 +00:00
|
|
|
debug_info->set_shared(*shared);
|
2017-01-23 10:25:02 +00:00
|
|
|
debug_info->set_debugger_hints(shared->debugger_hints());
|
2017-05-31 14:26:58 +00:00
|
|
|
debug_info->set_debug_bytecode_array(heap->undefined_value());
|
|
|
|
debug_info->set_break_points(heap->empty_fixed_array());
|
2008-09-01 10:15:45 +00:00
|
|
|
|
|
|
|
// Link debug info to function.
|
|
|
|
shared->set_debug_info(*debug_info);
|
|
|
|
|
|
|
|
return debug_info;
|
|
|
|
}
|
|
|
|
|
2017-06-06 15:44:55 +00:00
|
|
|
Handle<CoverageInfo> Factory::NewCoverageInfo(
|
|
|
|
const ZoneVector<SourceRange>& slots) {
|
|
|
|
const int slot_count = static_cast<int>(slots.size());
|
|
|
|
|
|
|
|
const int length = CoverageInfo::FixedArrayLengthForSlotCount(slot_count);
|
|
|
|
Handle<CoverageInfo> info =
|
|
|
|
Handle<CoverageInfo>::cast(NewUninitializedFixedArray(length));
|
|
|
|
|
|
|
|
for (int i = 0; i < slot_count; i++) {
|
|
|
|
SourceRange range = slots[i];
|
|
|
|
info->InitializeSlot(i, range.start, range.end);
|
|
|
|
}
|
|
|
|
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
2017-01-18 10:28:40 +00:00
|
|
|
Handle<BreakPointInfo> Factory::NewBreakPointInfo(int source_position) {
|
|
|
|
Handle<BreakPointInfo> new_break_point_info =
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<BreakPointInfo>::cast(NewStruct(TUPLE2_TYPE, TENURED));
|
2017-01-18 10:28:40 +00:00
|
|
|
new_break_point_info->set_source_position(source_position);
|
|
|
|
new_break_point_info->set_break_point_objects(*undefined_value());
|
|
|
|
return new_break_point_info;
|
|
|
|
}
|
2008-09-01 10:15:45 +00:00
|
|
|
|
2017-08-01 16:41:20 +00:00
|
|
|
Handle<BreakPoint> Factory::NewBreakPoint(int id, Handle<String> condition) {
|
|
|
|
Handle<BreakPoint> new_break_point =
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<BreakPoint>::cast(NewStruct(TUPLE2_TYPE, TENURED));
|
2017-08-01 16:41:20 +00:00
|
|
|
new_break_point->set_id(id);
|
|
|
|
new_break_point->set_condition(*condition);
|
|
|
|
return new_break_point;
|
|
|
|
}
|
|
|
|
|
2017-04-03 14:58:49 +00:00
|
|
|
Handle<StackFrameInfo> Factory::NewStackFrameInfo() {
|
2017-08-30 09:54:45 +00:00
|
|
|
Handle<StackFrameInfo> stack_frame_info = Handle<StackFrameInfo>::cast(
|
|
|
|
NewStruct(STACK_FRAME_INFO_TYPE, NOT_TENURED));
|
2017-04-03 14:58:49 +00:00
|
|
|
stack_frame_info->set_line_number(0);
|
|
|
|
stack_frame_info->set_column_number(0);
|
|
|
|
stack_frame_info->set_script_id(0);
|
|
|
|
stack_frame_info->set_script_name(Smi::kZero);
|
|
|
|
stack_frame_info->set_script_name_or_source_url(Smi::kZero);
|
|
|
|
stack_frame_info->set_function_name(Smi::kZero);
|
|
|
|
stack_frame_info->set_flag(0);
|
|
|
|
return stack_frame_info;
|
|
|
|
}
|
|
|
|
|
2017-04-12 18:33:20 +00:00
|
|
|
Handle<SourcePositionTableWithFrameCache>
|
|
|
|
Factory::NewSourcePositionTableWithFrameCache(
|
|
|
|
Handle<ByteArray> source_position_table,
|
2017-11-07 09:35:59 +00:00
|
|
|
Handle<NumberDictionary> stack_frame_cache) {
|
2017-04-12 18:33:20 +00:00
|
|
|
Handle<SourcePositionTableWithFrameCache>
|
|
|
|
source_position_table_with_frame_cache =
|
|
|
|
Handle<SourcePositionTableWithFrameCache>::cast(
|
2017-08-30 09:54:45 +00:00
|
|
|
NewStruct(TUPLE2_TYPE, TENURED));
|
2017-04-12 18:33:20 +00:00
|
|
|
source_position_table_with_frame_cache->set_source_position_table(
|
|
|
|
*source_position_table);
|
|
|
|
source_position_table_with_frame_cache->set_stack_frame_cache(
|
|
|
|
*stack_frame_cache);
|
|
|
|
return source_position_table_with_frame_cache;
|
|
|
|
}
|
|
|
|
|
2014-07-07 13:27:37 +00:00
|
|
|
Handle<JSObject> Factory::NewArgumentsObject(Handle<JSFunction> callee,
|
2008-07-03 15:10:15 +00:00
|
|
|
int length) {
|
2015-02-14 00:14:46 +00:00
|
|
|
bool strict_mode_callee = is_strict(callee->shared()->language_mode()) ||
|
2015-11-04 14:56:11 +00:00
|
|
|
!callee->shared()->has_simple_parameters();
|
2014-07-07 13:27:37 +00:00
|
|
|
Handle<Map> map = strict_mode_callee ? isolate()->strict_arguments_map()
|
|
|
|
: isolate()->sloppy_arguments_map();
|
|
|
|
AllocationSiteUsageContext context(isolate(), Handle<AllocationSite>(),
|
|
|
|
false);
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(!isolate()->has_pending_exception());
|
2014-07-07 13:27:37 +00:00
|
|
|
Handle<JSObject> result = NewJSObjectFromMap(map);
|
|
|
|
Handle<Smi> value(Smi::FromInt(length), isolate());
|
2017-10-16 10:55:06 +00:00
|
|
|
Object::SetProperty(result, length_string(), value, LanguageMode::kStrict)
|
|
|
|
.Assert();
|
2014-07-07 13:27:37 +00:00
|
|
|
if (!strict_mode_callee) {
|
2017-10-16 10:55:06 +00:00
|
|
|
Object::SetProperty(result, callee_string(), callee, LanguageMode::kStrict)
|
|
|
|
.Assert();
|
2014-07-07 13:27:37 +00:00
|
|
|
}
|
|
|
|
return result;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-05 09:40:13 +00:00
|
|
|
Handle<JSWeakMap> Factory::NewJSWeakMap() {
|
|
|
|
// TODO(adamk): Currently the map is only created three times per
|
|
|
|
// isolate. If it's created more often, the map should be moved into the
|
|
|
|
// strong root list.
|
|
|
|
Handle<Map> map = NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
|
|
|
|
return Handle<JSWeakMap>::cast(NewJSObjectFromMap(map));
|
|
|
|
}
|
|
|
|
|
2017-04-27 14:48:32 +00:00
|
|
|
Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> native_context,
|
|
|
|
int number_of_properties) {
|
|
|
|
DCHECK(native_context->IsNativeContext());
|
2014-11-10 18:03:50 +00:00
|
|
|
const int kMapCacheSize = 128;
|
2015-05-05 13:59:08 +00:00
|
|
|
// We do not cache maps for too many properties or when running builtin code.
|
2017-04-27 14:48:32 +00:00
|
|
|
if (isolate()->bootstrapper()->IsActive()) {
|
|
|
|
return Map::Create(isolate(), number_of_properties);
|
|
|
|
}
|
|
|
|
// Use initial slow object proto map for too many properties.
|
|
|
|
if (number_of_properties > kMapCacheSize) {
|
|
|
|
return handle(native_context->slow_object_with_object_prototype_map(),
|
|
|
|
isolate());
|
2014-11-10 18:03:50 +00:00
|
|
|
}
|
|
|
|
if (number_of_properties == 0) {
|
|
|
|
// Reuse the initial map of the Object function if the literal has no
|
2016-03-01 16:05:38 +00:00
|
|
|
// predeclared properties.
|
2017-04-27 14:48:32 +00:00
|
|
|
return handle(native_context->object_function()->initial_map(), isolate());
|
2014-11-10 18:03:50 +00:00
|
|
|
}
|
2015-05-22 10:51:49 +00:00
|
|
|
|
2014-11-10 18:03:50 +00:00
|
|
|
int cache_index = number_of_properties - 1;
|
2017-04-27 14:48:32 +00:00
|
|
|
Handle<Object> maybe_cache(native_context->map_cache(), isolate());
|
2016-06-06 12:58:10 +00:00
|
|
|
if (maybe_cache->IsUndefined(isolate())) {
|
2015-06-02 10:15:06 +00:00
|
|
|
// Allocate the new map cache for the native context.
|
|
|
|
maybe_cache = NewFixedArray(kMapCacheSize, TENURED);
|
2017-04-27 14:48:32 +00:00
|
|
|
native_context->set_map_cache(*maybe_cache);
|
2015-05-22 10:51:49 +00:00
|
|
|
} else {
|
|
|
|
// Check to see whether there is a matching element in the cache.
|
2015-06-02 10:15:06 +00:00
|
|
|
Handle<FixedArray> cache = Handle<FixedArray>::cast(maybe_cache);
|
2014-11-10 18:03:50 +00:00
|
|
|
Object* result = cache->get(cache_index);
|
|
|
|
if (result->IsWeakCell()) {
|
|
|
|
WeakCell* cell = WeakCell::cast(result);
|
|
|
|
if (!cell->cleared()) {
|
2017-04-27 14:48:32 +00:00
|
|
|
Map* map = Map::cast(cell->value());
|
|
|
|
DCHECK(!map->is_dictionary_map());
|
|
|
|
return handle(map, isolate());
|
2014-11-10 18:03:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-06-02 10:15:06 +00:00
|
|
|
// Create a new map and add it to the cache.
|
|
|
|
Handle<FixedArray> cache = Handle<FixedArray>::cast(maybe_cache);
|
|
|
|
Handle<Map> map = Map::Create(isolate(), number_of_properties);
|
2017-04-27 14:48:32 +00:00
|
|
|
DCHECK(!map->is_dictionary_map());
|
2014-11-10 18:03:50 +00:00
|
|
|
Handle<WeakCell> cell = NewWeakCell(map);
|
|
|
|
cache->set(cache_index, *cell);
|
2014-04-02 13:30:36 +00:00
|
|
|
return map;
|
2008-09-25 07:46:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-11 14:00:55 +00:00
|
|
|
void Factory::SetRegExpAtomData(Handle<JSRegExp> regexp,
|
|
|
|
JSRegExp::Type type,
|
|
|
|
Handle<String> source,
|
|
|
|
JSRegExp::Flags flags,
|
|
|
|
Handle<Object> data) {
|
|
|
|
Handle<FixedArray> store = NewFixedArray(JSRegExp::kAtomDataSize);
|
|
|
|
|
2008-10-24 08:40:02 +00:00
|
|
|
store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
|
|
|
|
store->set(JSRegExp::kSourceIndex, *source);
|
2015-11-25 13:46:09 +00:00
|
|
|
store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags));
|
2008-10-24 08:40:02 +00:00
|
|
|
store->set(JSRegExp::kAtomPatternIndex, *data);
|
|
|
|
regexp->set_data(*store);
|
|
|
|
}
|
|
|
|
|
2014-11-10 18:03:50 +00:00
|
|
|
|
2009-03-11 14:00:55 +00:00
|
|
|
void Factory::SetRegExpIrregexpData(Handle<JSRegExp> regexp,
|
|
|
|
JSRegExp::Type type,
|
|
|
|
Handle<String> source,
|
|
|
|
JSRegExp::Flags flags,
|
|
|
|
int capture_count) {
|
|
|
|
Handle<FixedArray> store = NewFixedArray(JSRegExp::kIrregexpDataSize);
|
2011-07-05 06:19:53 +00:00
|
|
|
Smi* uninitialized = Smi::FromInt(JSRegExp::kUninitializedValue);
|
2009-03-11 14:00:55 +00:00
|
|
|
store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
|
|
|
|
store->set(JSRegExp::kSourceIndex, *source);
|
2015-11-25 13:46:09 +00:00
|
|
|
store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags));
|
2014-09-10 12:38:12 +00:00
|
|
|
store->set(JSRegExp::kIrregexpLatin1CodeIndex, uninitialized);
|
2011-07-05 06:19:53 +00:00
|
|
|
store->set(JSRegExp::kIrregexpUC16CodeIndex, uninitialized);
|
2016-10-07 13:05:07 +00:00
|
|
|
store->set(JSRegExp::kIrregexpMaxRegisterCountIndex, Smi::kZero);
|
2009-03-11 14:00:55 +00:00
|
|
|
store->set(JSRegExp::kIrregexpCaptureCountIndex,
|
|
|
|
Smi::FromInt(capture_count));
|
2016-06-15 06:48:31 +00:00
|
|
|
store->set(JSRegExp::kIrregexpCaptureNameMapIndex, uninitialized);
|
2009-03-11 14:00:55 +00:00
|
|
|
regexp->set_data(*store);
|
|
|
|
}
|
|
|
|
|
2016-10-14 11:46:43 +00:00
|
|
|
Handle<RegExpMatchInfo> Factory::NewRegExpMatchInfo() {
|
|
|
|
// Initially, the last match info consists of all fixed fields plus space for
|
|
|
|
// the match itself (i.e., 2 capture indices).
|
|
|
|
static const int kInitialSize = RegExpMatchInfo::kFirstCaptureIndex +
|
|
|
|
RegExpMatchInfo::kInitialCaptureIndices;
|
|
|
|
|
|
|
|
Handle<FixedArray> elems = NewFixedArray(kInitialSize);
|
|
|
|
Handle<RegExpMatchInfo> result = Handle<RegExpMatchInfo>::cast(elems);
|
|
|
|
|
|
|
|
result->SetNumberOfCaptureRegisters(RegExpMatchInfo::kInitialCaptureIndices);
|
|
|
|
result->SetLastSubject(*empty_string());
|
|
|
|
result->SetLastInput(*undefined_value());
|
|
|
|
result->SetCapture(0, 0);
|
|
|
|
result->SetCapture(1, 0);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2009-03-11 14:00:55 +00:00
|
|
|
|
2015-04-13 16:22:11 +00:00
|
|
|
Handle<Object> Factory::GlobalConstantFor(Handle<Name> name) {
|
|
|
|
if (Name::Equals(name, undefined_string())) return undefined_value();
|
2017-06-29 22:28:00 +00:00
|
|
|
if (Name::Equals(name, NaN_string())) return nan_value();
|
|
|
|
if (Name::Equals(name, Infinity_string())) return infinity_value();
|
2011-09-23 08:00:06 +00:00
|
|
|
return Handle<Object>::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-10 09:21:48 +00:00
|
|
|
Handle<Object> Factory::ToBoolean(bool value) {
|
2013-02-25 14:46:09 +00:00
|
|
|
return value ? true_value() : false_value();
|
2011-10-10 09:21:48 +00:00
|
|
|
}
|
|
|
|
|
2016-07-14 10:25:45 +00:00
|
|
|
Handle<String> Factory::ToPrimitiveHintString(ToPrimitiveHint hint) {
|
|
|
|
switch (hint) {
|
|
|
|
case ToPrimitiveHint::kDefault:
|
|
|
|
return default_string();
|
|
|
|
case ToPrimitiveHint::kNumber:
|
|
|
|
return number_string();
|
|
|
|
case ToPrimitiveHint::kString:
|
|
|
|
return string_string();
|
|
|
|
}
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2014-04-17 17:45:32 +00:00
|
|
|
|
2017-07-07 09:24:57 +00:00
|
|
|
Handle<Map> Factory::CreateSloppyFunctionMap(
|
|
|
|
FunctionMode function_mode, MaybeHandle<JSFunction> maybe_empty_function) {
|
2017-10-12 15:37:46 +00:00
|
|
|
bool has_prototype = IsFunctionModeWithPrototype(function_mode);
|
|
|
|
int header_size = has_prototype ? JSFunction::kSizeWithPrototype
|
|
|
|
: JSFunction::kSizeWithoutPrototype;
|
|
|
|
int descriptors_count = has_prototype ? 5 : 4;
|
|
|
|
int inobject_properties_count = 0;
|
|
|
|
if (IsFunctionModeWithName(function_mode)) ++inobject_properties_count;
|
|
|
|
|
|
|
|
Handle<Map> map = NewMap(
|
2017-10-18 20:14:09 +00:00
|
|
|
JS_FUNCTION_TYPE, header_size + inobject_properties_count * kPointerSize,
|
|
|
|
TERMINAL_FAST_ELEMENTS_KIND, inobject_properties_count);
|
2017-10-12 15:37:46 +00:00
|
|
|
map->set_has_prototype_slot(has_prototype);
|
|
|
|
map->set_is_constructor(has_prototype);
|
2016-07-18 15:35:37 +00:00
|
|
|
map->set_is_callable();
|
2017-07-07 09:24:57 +00:00
|
|
|
Handle<JSFunction> empty_function;
|
|
|
|
if (maybe_empty_function.ToHandle(&empty_function)) {
|
|
|
|
Map::SetPrototype(map, empty_function);
|
|
|
|
}
|
2017-07-13 09:33:22 +00:00
|
|
|
|
2017-10-12 15:37:46 +00:00
|
|
|
//
|
|
|
|
// Setup descriptors array.
|
|
|
|
//
|
|
|
|
Map::EnsureDescriptorSlack(map, descriptors_count);
|
2016-07-18 15:35:37 +00:00
|
|
|
|
|
|
|
PropertyAttributes ro_attribs =
|
|
|
|
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
|
2017-07-13 09:33:22 +00:00
|
|
|
PropertyAttributes rw_attribs =
|
|
|
|
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
|
2016-07-18 15:35:37 +00:00
|
|
|
PropertyAttributes roc_attribs =
|
|
|
|
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
|
|
|
|
|
2017-07-13 09:33:22 +00:00
|
|
|
int field_index = 0;
|
2016-07-18 15:35:37 +00:00
|
|
|
STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
|
2017-07-13 09:33:22 +00:00
|
|
|
{ // Add length accessor.
|
2017-10-27 09:06:44 +00:00
|
|
|
Descriptor d = Descriptor::AccessorConstant(
|
|
|
|
length_string(), function_length_accessor(), roc_attribs);
|
2016-07-18 15:35:37 +00:00
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC_ASSERT(JSFunction::kNameDescriptorIndex == 1);
|
2017-07-13 09:33:22 +00:00
|
|
|
if (IsFunctionModeWithName(function_mode)) {
|
|
|
|
// Add name field.
|
|
|
|
Handle<Name> name = isolate()->factory()->name_string();
|
|
|
|
Descriptor d = Descriptor::DataField(name, field_index++, roc_attribs,
|
|
|
|
Representation::Tagged());
|
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// Add name accessor.
|
2017-10-27 09:06:44 +00:00
|
|
|
Descriptor d = Descriptor::AccessorConstant(
|
|
|
|
name_string(), function_name_accessor(), roc_attribs);
|
2016-07-18 15:35:37 +00:00
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
2017-07-13 09:33:22 +00:00
|
|
|
{ // Add arguments accessor.
|
2017-10-27 09:06:44 +00:00
|
|
|
Descriptor d = Descriptor::AccessorConstant(
|
|
|
|
arguments_string(), function_arguments_accessor(), ro_attribs);
|
2016-07-18 15:35:37 +00:00
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
2017-07-13 09:33:22 +00:00
|
|
|
{ // Add caller accessor.
|
2017-10-27 09:06:44 +00:00
|
|
|
Descriptor d = Descriptor::AccessorConstant(
|
|
|
|
caller_string(), function_caller_accessor(), ro_attribs);
|
2016-07-18 15:35:37 +00:00
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
|
|
|
if (IsFunctionModeWithPrototype(function_mode)) {
|
2017-07-13 09:33:22 +00:00
|
|
|
// Add prototype accessor.
|
|
|
|
PropertyAttributes attribs =
|
|
|
|
IsFunctionModeWithWritablePrototype(function_mode) ? rw_attribs
|
|
|
|
: ro_attribs;
|
2017-10-27 09:06:44 +00:00
|
|
|
Descriptor d = Descriptor::AccessorConstant(
|
|
|
|
prototype_string(), function_prototype_accessor(), attribs);
|
2016-07-18 15:35:37 +00:00
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
2017-07-13 09:33:22 +00:00
|
|
|
DCHECK_EQ(inobject_properties_count, field_index);
|
2017-10-12 15:37:46 +00:00
|
|
|
return map;
|
2016-07-18 15:35:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Handle<Map> Factory::CreateStrictFunctionMap(
|
|
|
|
FunctionMode function_mode, Handle<JSFunction> empty_function) {
|
2017-10-12 15:37:46 +00:00
|
|
|
bool has_prototype = IsFunctionModeWithPrototype(function_mode);
|
|
|
|
int header_size = has_prototype ? JSFunction::kSizeWithPrototype
|
|
|
|
: JSFunction::kSizeWithoutPrototype;
|
2017-07-13 09:33:22 +00:00
|
|
|
int inobject_properties_count = 0;
|
|
|
|
if (IsFunctionModeWithName(function_mode)) ++inobject_properties_count;
|
|
|
|
if (IsFunctionModeWithHomeObject(function_mode)) ++inobject_properties_count;
|
2017-10-12 15:37:46 +00:00
|
|
|
int descriptors_count = (IsFunctionModeWithPrototype(function_mode) ? 3 : 2) +
|
|
|
|
inobject_properties_count;
|
2017-07-24 14:12:51 +00:00
|
|
|
|
2017-10-12 15:37:46 +00:00
|
|
|
Handle<Map> map = NewMap(
|
2017-10-18 20:14:09 +00:00
|
|
|
JS_FUNCTION_TYPE, header_size + inobject_properties_count * kPointerSize,
|
|
|
|
TERMINAL_FAST_ELEMENTS_KIND, inobject_properties_count);
|
2017-10-12 15:37:46 +00:00
|
|
|
map->set_has_prototype_slot(has_prototype);
|
|
|
|
map->set_is_constructor(has_prototype);
|
|
|
|
map->set_is_callable();
|
|
|
|
Map::SetPrototype(map, empty_function);
|
2017-07-13 09:33:22 +00:00
|
|
|
|
2017-10-12 15:37:46 +00:00
|
|
|
//
|
|
|
|
// Setup descriptors array.
|
|
|
|
//
|
|
|
|
Map::EnsureDescriptorSlack(map, descriptors_count);
|
2016-07-18 15:35:37 +00:00
|
|
|
|
|
|
|
PropertyAttributes rw_attribs =
|
|
|
|
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
|
|
|
|
PropertyAttributes ro_attribs =
|
|
|
|
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
|
|
|
|
PropertyAttributes roc_attribs =
|
|
|
|
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
|
|
|
|
|
2017-07-13 09:33:22 +00:00
|
|
|
int field_index = 0;
|
2016-07-18 15:35:37 +00:00
|
|
|
STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
|
2017-07-13 09:33:22 +00:00
|
|
|
{ // Add length accessor.
|
2017-10-27 09:06:44 +00:00
|
|
|
Descriptor d = Descriptor::AccessorConstant(
|
|
|
|
length_string(), function_length_accessor(), roc_attribs);
|
2016-07-18 15:35:37 +00:00
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC_ASSERT(JSFunction::kNameDescriptorIndex == 1);
|
2017-07-13 09:33:22 +00:00
|
|
|
if (IsFunctionModeWithName(function_mode)) {
|
|
|
|
// Add name field.
|
|
|
|
Handle<Name> name = isolate()->factory()->name_string();
|
|
|
|
Descriptor d = Descriptor::DataField(name, field_index++, roc_attribs,
|
|
|
|
Representation::Tagged());
|
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// Add name accessor.
|
2017-10-27 09:06:44 +00:00
|
|
|
Descriptor d = Descriptor::AccessorConstant(
|
|
|
|
name_string(), function_name_accessor(), roc_attribs);
|
2016-07-18 15:35:37 +00:00
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
2017-07-13 09:33:22 +00:00
|
|
|
|
2016-07-18 15:35:37 +00:00
|
|
|
if (IsFunctionModeWithPrototype(function_mode)) {
|
2017-07-13 09:33:22 +00:00
|
|
|
// Add prototype accessor.
|
2016-07-18 15:35:37 +00:00
|
|
|
PropertyAttributes attribs =
|
2017-07-13 09:33:22 +00:00
|
|
|
IsFunctionModeWithWritablePrototype(function_mode) ? rw_attribs
|
2016-07-18 15:35:37 +00:00
|
|
|
: ro_attribs;
|
2017-10-27 09:06:44 +00:00
|
|
|
Descriptor d = Descriptor::AccessorConstant(
|
|
|
|
prototype_string(), function_prototype_accessor(), attribs);
|
2016-07-18 15:35:37 +00:00
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
2017-07-13 09:33:22 +00:00
|
|
|
|
|
|
|
if (IsFunctionModeWithHomeObject(function_mode)) {
|
|
|
|
// Add home object field.
|
|
|
|
Handle<Name> name = isolate()->factory()->home_object_symbol();
|
|
|
|
Descriptor d = Descriptor::DataField(name, field_index++, DONT_ENUM,
|
|
|
|
Representation::Tagged());
|
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
|
|
|
DCHECK_EQ(inobject_properties_count, field_index);
|
2017-10-12 15:37:46 +00:00
|
|
|
return map;
|
2016-07-18 15:35:37 +00:00
|
|
|
}
|
|
|
|
|
2016-12-07 10:34:15 +00:00
|
|
|
Handle<Map> Factory::CreateClassFunctionMap(Handle<JSFunction> empty_function) {
|
2017-10-12 15:37:46 +00:00
|
|
|
Handle<Map> map = NewMap(JS_FUNCTION_TYPE, JSFunction::kSizeWithPrototype);
|
|
|
|
map->set_has_prototype_slot(true);
|
2016-12-07 10:34:15 +00:00
|
|
|
map->set_is_constructor(true);
|
|
|
|
map->set_is_callable();
|
|
|
|
Map::SetPrototype(map, empty_function);
|
|
|
|
|
2017-10-12 15:37:46 +00:00
|
|
|
//
|
|
|
|
// Setup descriptors array.
|
|
|
|
//
|
2016-12-07 10:34:15 +00:00
|
|
|
Map::EnsureDescriptorSlack(map, 2);
|
|
|
|
|
2017-11-10 16:00:13 +00:00
|
|
|
PropertyAttributes rw_attribs =
|
|
|
|
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
|
2016-12-07 10:34:15 +00:00
|
|
|
PropertyAttributes roc_attribs =
|
|
|
|
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
|
|
|
|
|
|
|
|
STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
|
2017-07-13 09:33:22 +00:00
|
|
|
{ // Add length accessor.
|
2017-10-27 09:06:44 +00:00
|
|
|
Descriptor d = Descriptor::AccessorConstant(
|
|
|
|
length_string(), function_length_accessor(), roc_attribs);
|
2016-12-07 10:34:15 +00:00
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2017-07-13 09:33:22 +00:00
|
|
|
// Add prototype accessor.
|
2017-10-27 09:06:44 +00:00
|
|
|
Descriptor d = Descriptor::AccessorConstant(
|
2017-11-10 16:00:13 +00:00
|
|
|
prototype_string(), function_prototype_accessor(), rw_attribs);
|
2016-12-07 10:34:15 +00:00
|
|
|
map->AppendDescriptor(&d);
|
|
|
|
}
|
2017-10-12 15:37:46 +00:00
|
|
|
return map;
|
2016-12-07 10:34:15 +00:00
|
|
|
}
|
|
|
|
|
2017-11-08 12:56:08 +00:00
|
|
|
// static
|
|
|
|
NewFunctionArgs NewFunctionArgs::ForWasm(Handle<String> name, Handle<Code> code,
|
|
|
|
Handle<Map> map) {
|
|
|
|
NewFunctionArgs args;
|
|
|
|
args.name_ = name;
|
|
|
|
args.maybe_map_ = map;
|
|
|
|
args.maybe_code_ = code;
|
|
|
|
args.language_mode_ = LanguageMode::kSloppy;
|
|
|
|
args.prototype_mutability_ = MUTABLE;
|
|
|
|
|
|
|
|
return args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
NewFunctionArgs NewFunctionArgs::ForBuiltin(Handle<String> name,
|
|
|
|
Handle<Code> code, Handle<Map> map,
|
|
|
|
int builtin_id) {
|
|
|
|
DCHECK(Builtins::IsBuiltinId(builtin_id));
|
|
|
|
|
|
|
|
NewFunctionArgs args;
|
|
|
|
args.name_ = name;
|
|
|
|
args.maybe_map_ = map;
|
|
|
|
args.maybe_code_ = code;
|
|
|
|
args.maybe_builtin_id_ = builtin_id;
|
|
|
|
args.language_mode_ = LanguageMode::kStrict;
|
|
|
|
args.prototype_mutability_ = MUTABLE;
|
|
|
|
|
|
|
|
args.SetShouldSetLanguageMode();
|
|
|
|
|
|
|
|
return args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
NewFunctionArgs NewFunctionArgs::ForFunctionWithoutCode(
|
|
|
|
Handle<String> name, Handle<Map> map, LanguageMode language_mode) {
|
|
|
|
NewFunctionArgs args;
|
|
|
|
args.name_ = name;
|
|
|
|
args.maybe_map_ = map;
|
|
|
|
args.language_mode_ = language_mode;
|
|
|
|
args.prototype_mutability_ = MUTABLE;
|
|
|
|
|
|
|
|
args.SetShouldSetLanguageMode();
|
|
|
|
|
|
|
|
return args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
NewFunctionArgs NewFunctionArgs::ForBuiltinWithPrototype(
|
|
|
|
Handle<String> name, Handle<Code> code, Handle<Object> prototype,
|
|
|
|
InstanceType type, int instance_size, int inobject_properties,
|
|
|
|
int builtin_id, MutableMode prototype_mutability) {
|
|
|
|
DCHECK(Builtins::IsBuiltinId(builtin_id));
|
|
|
|
|
|
|
|
NewFunctionArgs args;
|
|
|
|
args.name_ = name;
|
|
|
|
args.maybe_code_ = code;
|
|
|
|
args.type_ = type;
|
|
|
|
args.instance_size_ = instance_size;
|
|
|
|
args.inobject_properties_ = inobject_properties;
|
|
|
|
args.maybe_prototype_ = prototype;
|
|
|
|
args.maybe_builtin_id_ = builtin_id;
|
|
|
|
args.language_mode_ = LanguageMode::kStrict;
|
|
|
|
args.prototype_mutability_ = prototype_mutability;
|
|
|
|
|
|
|
|
args.SetShouldCreateAndSetInitialMap();
|
|
|
|
args.SetShouldSetPrototype();
|
|
|
|
args.SetShouldSetLanguageMode();
|
|
|
|
|
|
|
|
return args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
NewFunctionArgs NewFunctionArgs::ForBuiltinWithoutPrototype(
|
|
|
|
Handle<String> name, Handle<Code> code, int builtin_id,
|
|
|
|
LanguageMode language_mode) {
|
|
|
|
DCHECK(Builtins::IsBuiltinId(builtin_id));
|
|
|
|
|
|
|
|
NewFunctionArgs args;
|
|
|
|
args.name_ = name;
|
|
|
|
args.maybe_code_ = code;
|
|
|
|
args.maybe_builtin_id_ = builtin_id;
|
|
|
|
args.language_mode_ = language_mode;
|
|
|
|
args.prototype_mutability_ = MUTABLE;
|
|
|
|
|
|
|
|
args.SetShouldSetLanguageMode();
|
|
|
|
|
|
|
|
return args;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewFunctionArgs::SetShouldCreateAndSetInitialMap() {
|
|
|
|
// Needed to create the initial map.
|
|
|
|
maybe_prototype_.Assert();
|
|
|
|
DCHECK_NE(kUninitialized, instance_size_);
|
|
|
|
DCHECK_NE(kUninitialized, inobject_properties_);
|
|
|
|
|
|
|
|
should_create_and_set_initial_map_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewFunctionArgs::SetShouldSetPrototype() {
|
|
|
|
maybe_prototype_.Assert();
|
|
|
|
should_set_prototype_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewFunctionArgs::SetShouldSetLanguageMode() {
|
|
|
|
DCHECK(language_mode_ == LanguageMode::kStrict ||
|
|
|
|
language_mode_ == LanguageMode::kSloppy);
|
|
|
|
should_set_language_mode_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<Map> NewFunctionArgs::GetMap(Isolate* isolate) const {
|
|
|
|
if (!maybe_map_.is_null()) {
|
|
|
|
return maybe_map_.ToHandleChecked();
|
|
|
|
} else if (maybe_prototype_.is_null()) {
|
|
|
|
return is_strict(language_mode_)
|
|
|
|
? isolate->strict_function_without_prototype_map()
|
|
|
|
: isolate->sloppy_function_without_prototype_map();
|
|
|
|
} else {
|
|
|
|
DCHECK(!maybe_prototype_.is_null());
|
|
|
|
switch (prototype_mutability_) {
|
|
|
|
case MUTABLE:
|
|
|
|
return is_strict(language_mode_) ? isolate->strict_function_map()
|
|
|
|
: isolate->sloppy_function_map();
|
|
|
|
case IMMUTABLE:
|
|
|
|
return is_strict(language_mode_)
|
|
|
|
? isolate->strict_function_with_readonly_prototype_map()
|
|
|
|
: isolate->sloppy_function_with_readonly_prototype_map();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2015-06-01 22:46:54 +00:00
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|